Branch data Line data Source code
1 : : !!****m* ABINIT/m_rec
2 : : !! NAME
3 : : !! m_rec
4 : : !!
5 : : !! FUNCTION
6 : : !! This module provides some functions applied to the
7 : : !! recursion structured datatype recursion_type.
8 : : !! It includes also some function used to change some variables
9 : : !! of recursion_type
10 : : !!
11 : : !! COPYRIGHT
12 : : !! Copyright (C) 2002-2026 ABINIT group (MMancini)
13 : : !! This file is distributed under the terms of the
14 : : !! GNU General Public License, see ~abinit/COPYING
15 : : !! or http://www.gnu.org/copyleft/gpl.txt .
16 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt.
17 : : !!
18 : : !! NOTES
19 : : !!
20 : : !! * Routines tagged with "@type_name" are strongly connected to the definition of the data type.
21 : : !! Strongly connected means that the proper functioning of the implementation relies on the
22 : : !! assumption that the tagged procedure is consistent with the type declaration.
23 : : !! Every time a developer changes the structure "type_name" adding new entries, he/she has to make sure
24 : : !! that all the strongly connected routines are changed accordingly to accomodate the modification of the data type.
25 : : !! Typical examples of strongly connected routines are creation, destruction or reset methods.
26 : : !!
27 : : !!
28 : : !! SOURCE
29 : :
30 : : #if defined HAVE_CONFIG_H
31 : : #include "config.h"
32 : : #endif
33 : :
34 : : #include "abi_common.h"
35 : :
36 : : module m_rec
37 : :
38 : : use defs_basis
39 : : use defs_rectypes
40 : : use m_abicore
41 : : use m_errors
42 : : use m_xmpi
43 : : use m_sort
44 : : use m_dtset
45 : :
46 : : use defs_datatypes, only : pseudopotential_type
47 : : use defs_abitypes, only : mpi_type
48 : : use m_exp_mat, only : exp_mat
49 : : use m_numeric_tools, only : set2unit
50 : : use m_special_funcs, only : gamma_function
51 : : use m_pawfgr, only : pawfgr_nullify, indgrid, pawfgr_destroy
52 : : use m_paw_sphharm, only : initylmr
53 : : use m_time, only : timab
54 : : use m_rec_tools, only : get_pt0_pt1
55 : : use m_per_cond, only : per_cond
56 : : #ifdef HAVE_GPU_CUDA
57 : : use m_hidecudarec, only : InitRecGPU, CleanRecGPU
58 : : #endif
59 : :
60 : : implicit none
61 : :
62 : : private :: &
63 : : find_maxmin_proc, & !--To calculate max and min pt for any cpu
64 : : H_D_distrib
65 : :
66 : : public :: &
67 : : InitRec, & !--Main creation method.
68 : : Init_MetricRec, & !--To Initalize the inf. metric in recursion
69 : : Init_nlpspRec, & !--Main creation method for non-local part.
70 : : CleanRec, & !--deallocate all pointers.
71 : : Calcnrec, & !--calculates the new min_nrec
72 : : cpu_distribution !--Regulates the work load on cpu-gpu
73 : : CONTAINS !===========================================================
74 : : !!***
75 : :
76 : : !!****f* m_rec/H_D_distrib
77 : : !! NAME
78 : : !! H_D_distrib
79 : : !!
80 : : !! FUNCTION
81 : : !! Calculate the number of point,GPU,for any proc
82 : : !!
83 : : !! INPUTS
84 : : !! rset<recursion_type>= recursion variables
85 : : !! cpu (-1 if there are not gpu)
86 : : !! nfft=nuber of point of the fine grid
87 : : !! ngfftrec=nuber of point of one edge of the coarse grid
88 : : !! gratio=recgratio ratio between the fine and coarse grid
89 : : !! beta_coeff=estimated time ratio between CPU_time and GPU_time
90 : : !!
91 : : !! OUTPUT
92 : : !! proc_pt_dev(2,0:nproc-1) which device and how many points
93 : : !! that proc has to compute: proc_pt_dev(1,iproc) which device
94 : : !! associated to proc i (-1 if none), proc_pt_dev(2,iproc) how
95 : : !! many points
96 : : !!
97 : : !! SOURCE
98 : :
99 : 6 : subroutine H_D_distrib(rset,nfft,gratio,proc_pt_dev,beta_coeff)
100 : :
101 : : !Arguments ------------------------------------
102 : : integer, intent(in) :: nfft,gratio
103 : : real(dp),intent(in) :: beta_coeff
104 : : integer,pointer :: proc_pt_dev(:,:)
105 : : type(recursion_type),intent(inout) :: rset
106 : : !Local ---------------------------
107 : : integer :: me,icpu,resto,ntot,ngpu
108 : : integer :: n_per_cpu,n_per_gpu
109 : : character(500) :: msg
110 : : #ifdef HAVE_GPU_CUDA
111 : : integer,pointer :: ndev(:)
112 : : #else
113 : 12 : integer :: ndev(0:rset%mpi%nproc-1)
114 : : #endif
115 : : ! *********************************************************************
116 : :
117 : :
118 : : #ifdef HAVE_GPU_CUDA
119 : : ndev => rset%GPU%map
120 : : #else
121 [ + + ]: 24 : ndev = -1
122 : : #endif
123 : :
124 : 6 : me = rset%mpi%me
125 : 6 : ntot = nfft/(gratio*gratio*gratio)
126 : 6 : ngpu = rset%ngpu
127 : :
128 : : !--If sequential code all points are computed by the proc 0
129 [ + + ]: 6 : if(rset%mpi%nproc ==1) then
130 : 2 : proc_pt_dev(1,0) = ndev(0)
131 : 2 : proc_pt_dev(2,0) = ntot
132 : 2 : return
133 : : end if
134 : :
135 : : !--Number of points for any cpu
136 : 4 : n_per_cpu = int(int(ntot/(rset%mpi%nproc+ngpu*(beta_coeff-1.d0))))
137 : 4 : n_per_gpu = int(n_per_cpu*beta_coeff)
138 : : !write(std_out,*)'n_per_cpu',n_per_cpu
139 : : !write(std_out,*)'rset%GPU%map',rset%GPU%map
140 [ + + ]: 20 : do icpu=0,rset%mpi%nproc-1
141 : 16 : proc_pt_dev(1,icpu) = ndev(icpu)
142 : 16 : proc_pt_dev(2,icpu) = n_per_cpu
143 [ - + ]: 20 : if(ndev(icpu)>-1) proc_pt_dev(2,icpu) = n_per_gpu
144 : : end do
145 : :
146 : : !--Distribute the rest
147 [ + + ]: 20 : resto = ntot-sum(proc_pt_dev(2,:))
148 : 4 : icpu = 0
149 : : !write(std_out,*)'rest',resto,ngpu
150 [ - + ]: 4 : if(resto>0) then
151 [ # # ]: 0 : if(ngpu/=0) then
152 : : !--distribute rest only on GPU
153 [ # # ]: 0 : do while(resto/=0)
154 [ # # ]: 0 : if(proc_pt_dev(1,icpu)>-1) then
155 : 0 : proc_pt_dev(2,icpu) = proc_pt_dev(2,icpu)+1
156 : 0 : resto = resto-1
157 : : endif
158 : 0 : icpu = mod(icpu+1,rset%mpi%nproc)
159 : : enddo
160 : : else
161 : : !--distribute rest on all CPU
162 [ # # ]: 0 : do while(resto/=0)
163 : 0 : proc_pt_dev(2,icpu) = proc_pt_dev(2,icpu)+1
164 : 0 : resto = resto-1
165 : 0 : icpu = mod(icpu+1,rset%mpi%nproc)
166 : : enddo
167 : : return
168 : : endif
169 : : endif
170 : :
171 : : !--Printing GPU and load distribution on procs
172 : : write(msg,'(3a)')&
173 : 4 : & ' -Load on procs------------',ch10,&
174 : 8 : & ' me device points'
175 : 4 : call wrtout(std_out,msg,'COLL')
176 [ + + ]: 20 : do icpu=0,rset%mpi%nproc-1
177 : 16 : write(msg,'(i5,i8,i14)') icpu,proc_pt_dev(:,icpu);
178 : 20 : call wrtout(std_out,msg,'COLL')
179 : : end do
180 : :
181 : : end subroutine H_D_distrib
182 : : !!***
183 : :
184 : :
185 : :
186 : : !!****f* m_rec/find_maxmin_proc
187 : : !! NAME
188 : : !! find_maxmin_proc
189 : : !!
190 : : !! FUNCTION
191 : : !! To calculate max and min pt for any cpu, it is useful for
192 : : !! recgratio!=1
193 : : !!
194 : : !! INPUTS
195 : : !! nproc = number of procs
196 : : !! me = identity of the proc
197 : : !! ngfft(3) = fine grid (corresponds to dtset%ngfft(1:3))
198 : : !! proc_pt_dev(2,0:nproc-1) which device and how many points
199 : : !! recpar%npt = number of points computed by the proc me (see side effects)
200 : : !!
201 : : !! OUTPUT
202 : : !! recpar%pt0<type(vec_int)>=Intial point for this proc in x,y,z
203 : : !! recpar%pt1<type(vec_int)>=Final point for this proc in x,y,z
204 : : !! recpar%min_pt=Intial point for this proc
205 : : !! recpar%max_pt=Final point for this proc
206 : : !!
207 : : !! SIDE EFFECTS
208 : : !! recpar%ntranche=number of pts computed by the proc me on the fine grid.
209 : : !!
210 : : !!
211 : : !! So when recgratio!=1, ntranche will not correspond to the npt!
212 : : !!
213 : : !! SOURCE
214 : :
215 : 6 : subroutine find_maxmin_proc(recpar,nproc,me,gratio,ngfft,proc_pt_dev)
216 : :
217 : : !Arguments ------------------------------------
218 : : integer,intent(in) :: nproc,me,gratio
219 : : integer,intent(in) :: ngfft(3)
220 : : type(recparall_type),intent(inout) :: recpar
221 : : integer,pointer :: proc_pt_dev(:,:)
222 : : !Local ---------------------------
223 : : integer :: pointoncpu
224 : : integer :: nfft,ntot,ii
225 : : integer :: inf,sup
226 : 12 : integer :: proc_limit(0:nproc-1)
227 : : ! *********************************************************************
228 : : ! write(std_out,*)'start find_maxmin_proc'
229 : 6 : recpar%npt = 0
230 : : nfft = product(ngfft)
231 : 6 : ntot = nfft/(gratio*gratio*gratio)
232 : 6 : pointoncpu = ntot/nproc
233 : :
234 [ + - + + : 90 : proc_limit = (/(sum(proc_pt_dev(2,:ii)),ii=0,nproc-1)/)
+ + + + ]
235 : :
236 [ + + ]: 6 : if(gratio==1)then
237 : 5 : recpar%ntranche = proc_limit(me)
238 [ + + ]: 5 : if(me/=0) recpar%ntranche = recpar%ntranche-proc_limit(me-1)
239 : : endif
240 : :
241 : 6 : inf=0
242 [ + + ]: 6 : if(me/=0) inf = proc_limit(me-1)
243 : 6 : sup = proc_limit(me)
244 : :
245 : :
246 : 6 : call get_pt0_pt1(ngfft,gratio,inf,sup,recpar)
247 : :
248 : 6 : recpar%npt = sup-inf
249 : :
250 : : !write(std_out,*)'exit find_maxmin_proc'
251 : 6 : end subroutine find_maxmin_proc
252 : : !!***
253 : :
254 : : !!****f* m_rec/cpu_distribution
255 : : !! NAME
256 : : !! cpu_distribution
257 : : !!
258 : : !! FUNCTION
259 : : !! Calculate the number of point,GPU,for any proc
260 : : !!
261 : : !! INPUTS
262 : : !! ngfft(3)=nuber of point of the grid
263 : : !! gratio=recgratio ratio between the fine and coarse grid
264 : : !! beta_coeff=estimated time ratio between CPU_time and GPU_time
265 : : !! calc_type=if 0 takes the possible max for nptrec (to test the
266 : : !! completly full graphic card). 1 after test to calculate the min
267 : : !! possible value for nptrec
268 : : !!
269 : : !! OUTPUT
270 : : !!
271 : : !! SOURCE
272 : :
273 : 6 : subroutine cpu_distribution(gratio,rset,ngfft,beta_coeff,calc_type)
274 : :
275 : : !Arguments ------------------------------------
276 : : integer,intent(in) :: gratio,calc_type
277 : : real(dp),intent(in) :: beta_coeff
278 : : integer,intent(in) :: ngfft(3)
279 : : type(recursion_type),intent(inout),target :: rset
280 : : !Local ---------------------------
281 : : integer :: ii,nfft,ierr
282 : 6 : integer,pointer :: proc_pt_dev(:,:)
283 : : type(recparall_type),pointer :: recpar
284 : : character(500) :: msg
285 : : ! *********************************************************************
286 : :
287 : : ! write(std_out,*)'start cpu_distribution'
288 : :
289 : : nullify(proc_pt_dev)
290 [ - + + - : 18 : ABI_MALLOC(proc_pt_dev,(2,0:rset%mpi%nproc-1))
+ - + - -
+ - + ]
291 : :
292 [ + + ]: 24 : nfft = product(ngfft)
293 : 6 : call H_D_distrib(rset,nfft,gratio,proc_pt_dev,beta_coeff)
294 : :
295 : 6 : nullify(recpar)
296 [ + - ]: 6 : if(rset%load == 0)then
297 [ - + + - : 18 : ABI_MALLOC(rset%par%displs,(0:rset%mpi%nproc-1))
+ - + - -
+ - + -
+ ]
298 [ - + + - : 18 : ABI_MALLOC(rset%par%vcount,(0:rset%mpi%nproc-1))
+ - + - -
+ - + -
+ ]
299 : 6 : recpar => rset%par
300 : : #if defined HAVE_GPU_CUDA
301 : : else
302 : : if(rset%tp==4)then
303 : : if(.not. allocated(rset%GPU%par%displs)) then
304 : : ABI_MALLOC(rset%GPU%par%displs,(0:rset%mpi%nproc-1))
305 : : ABI_MALLOC(rset%GPU%par%vcount,(0:rset%mpi%nproc-1))
306 : : end if
307 : : endif
308 : : recpar => rset%GPU%par
309 : : #endif
310 : : endif
311 : :
312 : 6 : recpar%ntranche = nfft/(rset%mpi%nproc)!equipartitioned point
313 : :
314 : : call find_maxmin_proc(recpar,rset%mpi%nproc,&
315 : 6 : & rset%mpi%me,gratio,ngfft,proc_pt_dev)
316 : :
317 [ + + ]: 24 : recpar%vcount = 0
318 [ + - ]: 6 : if(rset%load==0)then
319 : 6 : recpar%vcount(rset%mpi%me) = recpar%ntranche
320 : : else
321 : 0 : recpar%vcount(rset%mpi%me) = recpar%npt
322 : : endif
323 : :
324 : 6 : call xmpi_sum(recpar%vcount,rset%mpi%comm_bandfft,ierr)
325 : :
326 [ + + ]: 24 : recpar%displs = 0
327 [ + + + - : 58 : if(rset%mpi%nproc>1) recpar%displs(1:) = (/(sum(recpar%vcount(:ii)),ii=0,rset%mpi%nproc-2)/)
+ + + + +
+ ]
328 : :
329 : : !--INITALIZATION OF CUDA FOR RECURSION
330 : : #if defined HAVE_GPU_CUDA
331 : : if(rset%load == 0) rset%GPU%par = rset%par
332 : : call InitRecGPU(rset,nfft,gratio,rset%GPU%map(rset%mpi%me),calc_type)
333 : : #else
334 : : ierr = calc_type !only of abirule when there is not HAVE_GPU_CUDA
335 : : #endif
336 : :
337 : :
338 : : ! if(rset%debug ) then
339 : : write(msg,'(a,i7,2(2a,3i7),8(2a,i7),2(2a,3i7),(2a,e14.6))')&
340 : 6 : & ' me ', rset%mpi%me,ch10,&
341 : 6 : & ' ngfft ', ngfft(1:3),ch10,&
342 : 6 : & ' ngfftrec ', rset%ngfftrec(1:3),ch10,&
343 : 6 : & ' load ', rset%load,ch10,&
344 : 6 : & ' ntranche ', recpar%ntranche,ch10,&
345 : 6 : & ' min_pt ', recpar%min_pt,ch10,&
346 : 6 : & ' max_pt ', recpar%max_pt,ch10,&
347 : 6 : & ' rset%mpi%nproc ', rset%mpi%nproc,ch10,&
348 : 6 : & ' rset%mpi%nproc_fft ', rset%mpi%nproc_fft,ch10,&
349 : 6 : & ' dtset%ngfft(10) ', rset%ngfftrec(10),ch10,&
350 : 6 : & ' recpar%npt ', recpar%npt,ch10,&
351 : 6 : & ' recpar%pt0 ', recpar%pt0%x,recpar%pt0%y,recpar%pt0%z,ch10,&
352 : 6 : & ' recpar%pt1 ', recpar%pt1%x,recpar%pt1%y,recpar%pt1%z,ch10,&
353 : 12 : & ' grid step ', rset%inf%tr(1)
354 : 6 : call wrtout(std_out,msg,'PERS')
355 : : #if defined HAVE_GPU_CUDA
356 : : write(msg,'(a,i7,2(2a,i7),a)')&
357 : : & ' rset%ngp ', rset%ngpu,ch10,&
358 : : & ' gpudevice ', rset%gpudevice,ch10,&
359 : : & ' nptrec ', rset%GPU%nptrec,ch10
360 : : call wrtout(std_out,msg,'PERS')
361 : : #endif
362 : : ! write(std_out,*)'display',recpar%displs
363 : : ! write(std_out,*)'vcount',recpar%vcount
364 : : ! end if
365 : :
366 : :
367 : 6 : nullify(recpar)
368 [ + - ]: 6 : if(associated(proc_pt_dev)) then
369 : 6 : ABI_FREE(proc_pt_dev)
370 : : end if
371 : :
372 : : ! write(std_out,*)'exit from cpu_distribution'
373 : 6 : end subroutine cpu_distribution
374 : : !!***
375 : :
376 : :
377 : : !!****f* m_rec/InitRec
378 : : !! NAME
379 : : !! InitRec
380 : : !!
381 : : !! FUNCTION
382 : : !! Initialise the rset<recursion_type>=Data type concerning recursion.
383 : : !!
384 : : !! INPUTS
385 : : !! dtset <type(dataset_type)>=all input variables in this dataset
386 : : !! mpi_ab <type(mpi_type)=MPI-parallelisation information
387 : : !! mproj=0 if psp is only local
388 : : !!
389 : : !! SIDE EFFECTS
390 : : !! All pointers set to null().
391 : : !!
392 : : !!
393 : : !! SOURCE
394 : :
395 : 6 : subroutine InitRec(dtset,mpi_ab,rset,rmet,mproj)
396 : :
397 : : #ifdef HAVE_GPU_CUDA
398 : : use m_gpu_detect,only :get_topo,find_set_gpu
399 : : use m_hidecudarec,only :InitRecGPU_0
400 : : #include "cuda_common.h"
401 : : #endif
402 : :
403 : : !Arguments ------------------------------------
404 : : ! scalars
405 : : integer,intent(in) :: mproj
406 : : type(dataset_type),intent(in) :: dtset
407 : : type(MPI_type),intent(in),target :: mpi_ab
408 : : type(recursion_type),intent(inout) :: rset
409 : : real(dp),intent(in) :: rmet(3,3)
410 : : ! arrays
411 : : !Local ---------------------------
412 : : integer :: ii
413 : : real(dp) :: beta,rtrotter
414 : : #if defined HAVE_GPU_CUDA
415 : : character(500) :: msg
416 : : #endif
417 : : ! *********************************************************************
418 : : ! @recursion_type
419 : : ! @pawfgr_type
420 : :
421 : : !--Initialisation
422 : 6 : beta = one/dtset%tsmear !--Inverse of temperature
423 : : !--Rewriting the trotter parameter
424 : 6 : rtrotter = max(half,real(dtset%recptrott,dp))
425 : :
426 : 6 : rset%debug= (dtset%prtvol==-7)
427 : 6 : rset%quitrec = 0
428 : 6 : rset%min_nrec = dtset%recnrec
429 : 6 : rset%efermi = dtset%recefermi !initial guess for fermie
430 : :
431 : 6 : rset%nfftrec = 0
432 [ + + ]: 114 : rset%ngfftrec = 0
433 : :
434 : 6 : rset%tronc = .False.
435 : :
436 : 6 : rset%mpi => mpi_ab
437 : :
438 : : !--Are all pseudo-potentials local?
439 : 6 : rset%nl%nlpsp = (mproj/=0)
440 : : !--Some initialisation concerning the metrics
441 : : ! If non-local psps then it allocates the atoms positions
442 : : ! on the grid
443 [ - + ]: 6 : if(rset%nl%nlpsp) then
444 [ # # # # : 0 : ABI_MALLOC(rset%inf%gcart,(3,dtset%natom))
# # # # #
# # # #
# ]
445 : : else
446 [ - + - + ]: 6 : ABI_MALLOC(rset%inf%gcart,(0,0))
447 : : end if
448 [ - + - - ]: 6 : rset%inf%gcart = 0
449 : :
450 : : !----------------------------------------------------------
451 : : !--TRONCATION OF THE BOX
452 : : !! determines new dimensions the method is similar to the one used
453 : : !! in getng (except that ecut and xboxcutmin give no constraint,
454 : : !! and symmetries are not handled)
455 : :
456 : 6 : call getngrec(dtset%ngfft,rmet,rset%ngfftrec,rset%nfftrec,dtset%recrcut,0.25d0*sqrt(beta/rtrotter),rset%tronc)
457 : : ! 1/4*sqrt(beta/trotter) for guess - should be modified
458 : :
459 : : !------------------------------------------------------------
460 : : !--DETERMINING WHICH POINT WILL COMPUTE THAT PROC
461 : : !----------------------------------------------------------
462 : : !--Paralelism using the band communicator (not used in the recursion)
463 : : !--Distribution on procs with cuda
464 : :
465 : :
466 : 6 : rset%ngpu = 0 !--Initial guess no GPU at all
467 : 6 : rset%gpudevice = -1 !--Inital guess no GPU associated
468 : 6 : rset%load = 0 !--Inital homogeneous work load
469 : 6 : rset%tp = 0 !--Initial guess 1 cpu, 0 gpu
470 : :
471 : :
472 : : #ifdef HAVE_GPU_CUDA
473 : : !--Initialise GPU variables for recursion
474 : : call InitRecGPU_0(rset%GPU,mpi_ab)
475 : :
476 : : !--Get the distribution of GPUs on CPUs
477 : : call find_set_gpu(mpi_ab%nproc,mpi_ab%comm_bandfft,rset%GPU%map,rset%ngpu)
478 : :
479 : : !--Get the topology of the machine
480 : : call get_topo(rset%mpi%nproc,rset%ngpu,rset%tp)
481 : : if(rset%tp>4)then
482 : : msg = 'm_rec: number of gpu>number of cpu is not implemented'
483 : : ABI_ERROR(msg)
484 : : endif
485 : : ! rset%tp = 0;if(rset%mpi%nproc>1)rset%tp = 1
486 : : ! rset%ngpu = 0; rset%GPU%map=-1
487 : : !--For the moment cuda doesnt take into account non-local psp
488 : : if(rset%nl%nlpsp) then
489 : : rset%tp = 0;if(rset%mpi%nproc>1)rset%tp = 1
490 : : rset%GPU%map = -1
491 : : endif
492 : : #else
493 [ + + ]: 6 : if(rset%mpi%nproc>1)rset%tp = 1
494 : : #endif
495 : :
496 : : !--Basic initialization for recursion metric (only needed for printing)
497 [ + + ]: 24 : do ii=1,3
498 [ + + ]: 78 : rset%inf%rmet(ii,:) = rmet(ii,:)/(real(dtset%ngfft(1:3)*dtset%ngfft(ii),dp))
499 : : end do
500 [ + + ]: 24 : rset%inf%tr(:) = sqrt((/(rset%inf%rmet(ii,ii),ii=1,3)/)) !grid step
501 : :
502 : : !--Compute the work loqd distribution on devices (gpu,cpu)
503 : 6 : call cpu_distribution(dtset%recgratio,rset,dtset%ngfft(:3),1.d0,0)
504 : :
505 : : !------------------------------------------------------------
506 : : !--DEFINITION VARIABLE COARSE-FINE GRID TO USE TRANSGRID--INGRID FUNCTIONS
507 : 6 : call pawfgr_nullify(rset%pawfgr)
508 : : !if coarse grid is used
509 [ + + ]: 6 : if (dtset%recgratio>1) then
510 : : !fine grid--
511 : 1 : rset%pawfgr%mgfft = 0
512 [ + + ]: 4 : rset%pawfgr%nfft = product(dtset%ngfft(1:3))
513 [ + + ]: 19 : rset%pawfgr%ngfft(:) = dtset%ngfft(:)
514 [ + + ]: 4 : rset%pawfgr%ngfft(9:11)=(/0,1,0/)
515 [ + + ]: 3 : rset%pawfgr%ngfft(12:13)= dtset%ngfft(2:3)
516 : : !coarse grid--
517 : 1 : rset%pawfgr%mgfftc = 0
518 [ + + ]: 19 : rset%pawfgr%ngfftc(:) = rset%pawfgr%ngfft(:)
519 [ + + - + ]: 4 : rset%pawfgr%ngfftc(:3) = floor(real(dtset%ngfft(:3)+1,dp)/real(dtset%recgratio,dp))
520 [ + + ]: 4 : rset%pawfgr%nfftc = product(rset%pawfgr%ngfftc(1:3))
521 : :
522 : 1 : rset%pawfgr%usefinegrid = 1
523 [ - + + - : 3 : ABI_MALLOC(rset%pawfgr%fintocoa,(rset%pawfgr%nfft))
+ - + - -
+ - + ]
524 [ - + + - : 3 : ABI_MALLOC(rset%pawfgr%coatofin,(rset%pawfgr%nfftc))
+ - + - -
+ - + ]
525 : : call indgrid(rset%pawfgr%coatofin,rset%pawfgr%fintocoa,&
526 : : rset%pawfgr%nfftc,rset%pawfgr%nfft,&
527 : 1 : rset%pawfgr%ngfftc,rset%pawfgr%ngfft)
528 : :
529 : : else
530 : 5 : rset%pawfgr%mgfft = 0
531 [ + + ]: 95 : rset%pawfgr%ngfft = 0
532 : 5 : rset%pawfgr%mgfftc = 0
533 : :
534 : 5 : rset%pawfgr%usefinegrid = 0
535 : : end if
536 : :
537 : :
538 : 6 : end subroutine InitRec
539 : : !!***
540 : :
541 : : !!****f* m_rec/Init_MetricRec
542 : : !! NAME
543 : : !! Init_MetricRec
544 : : !!
545 : : !! FUNCTION
546 : : !! Initialise the rset<recursion_type>=Data type concerning recursion.
547 : : !! In particular, the information on the infinitesimal metric.
548 : : !! Also other variable are initialized
549 : : !!
550 : : !! INPUTS
551 : : !! rmet: metrics
552 : : !! ucvol=unit cell volume in bohr**3.
553 : : !! ngfft(1:3)=fine grid used in recursion
554 : : !! rprimd=Real space PRIMitive translations, Dimensional
555 : : !! xred=vectors (X) of atom positions in reduced coordinates
556 : : !! natom=number of atoms
557 : : !! debug=debug variable
558 : : !!
559 : : !! OUTPUT
560 : : !! metrec <type(metricrec_type)>= infinitesimal metrics used in recursion
561 : : !!
562 : : !! SOURCE
563 : :
564 : 11 : subroutine Init_MetricRec(metrec,nlpsp,rmet,ucvol,rprimd,xred,ngfft,natom,debug)
565 : :
566 : : !Arguments ------------------------------------
567 : : !scalars
568 : : integer, intent(in) ::natom
569 : : real(dp), intent(in) :: ucvol
570 : : logical,intent(in) ::nlpsp,debug
571 : : type(metricrec_type),intent(inout) :: metrec
572 : : !arrays
573 : : integer,intent(in) :: ngfft(3)
574 : : real(dp),intent(in) :: rmet(3,3),rprimd(3,3),xred(3,natom)
575 : :
576 : : !Local ---------------------------
577 : : integer :: ii
578 : 22 : real(dp) :: xcart(3,natom)
579 : : character(500) :: msg
580 : : ! *********************************************************************
581 : :
582 : : !--Intialisation of variables concerning the infinitesimal metric
583 [ + + ]: 44 : do ii=1,3
584 [ + + ]: 143 : metrec%rmet(ii,:) = rmet(ii,:)/(real(ngfft(1:3)*ngfft(ii),dp))
585 : : end do
586 [ + + ]: 44 : metrec%ucvol = ucvol/real(product(ngfft(1:3)),dp)
587 [ + + ]: 44 : metrec%tr(:) = sqrt((/(metrec%rmet(ii,ii),ii=1,3)/)) !grid step
588 : :
589 : : !--Initialisation of others variables
590 : : !--In non-loc-psp case: calculate the position of ions and conversion factor
591 [ - + ]: 11 : if(nlpsp) then
592 [ # # ]: 0 : do ii = 1,natom
593 [ # # # # : 0 : xcart(:,ii) = matmul(rprimd(:,:),xred(:,ii))
# # ]
594 : : end do
595 [ # # # # : 0 : metrec%gcart(:,:) = per_cond(natom,xcart,ngfft(1:3),metrec%tr(:))
# # ]
596 [ # # ]: 0 : if(debug) then
597 [ # # ]: 0 : do ii=1,natom
598 : 0 : write (msg,'(a,3f8.2)')'xcart=',xcart(:,ii)
599 : 0 : call wrtout(std_out,msg,'COLL')
600 : 0 : write (msg,'(a,3i4)')'gcart=',metrec%gcart(:,ii)
601 : 0 : call wrtout(std_out,msg,'COLL')
602 : : end do
603 : : end if
604 : : end if
605 : :
606 : 11 : end subroutine Init_MetricRec
607 : : !!***
608 : :
609 : : !!****f* m_rec/Init_nlpspRec
610 : : !! NAME
611 : : !! Init_nlpspRec
612 : : !!
613 : : !! FUNCTION
614 : : !! Initialise the rset<recursion_type>=Data type concerning recursion.
615 : : !! In particular, the non-local part of pseudo-potential.
616 : : !!
617 : : !! INPUTS
618 : : !! tempe=temperature
619 : : !! psps <type(pseudopotential_type)>=variables related to pseudo-potentials
620 : : !! metrec <type(metricrec_type)>=infinitesimal metrics used in recursion
621 : : !! ngfftrec(18)=Number of Grid points for Fast Fourier Transform for
622 : : !! Recursion (truncated box, if different from ngfft)
623 : : !! debug=debug variable
624 : : !!
625 : : !! SIDE EFFECTS
626 : : !! nlrec <type(nlpsprec_type)>=pseudo-potentials information for recursion
627 : : !!
628 : : !! SOURCE
629 : :
630 : 6 : subroutine Init_nlpspRec(tempe,psps,nlrec,metrec,ngfftrec,debug)
631 : :
632 : : !Arguments ------------------------------------
633 : : ! scalars
634 : : logical,intent(in) :: debug
635 : : real(dp), intent(in) :: tempe
636 : : type(pseudopotential_type),intent(in) ::psps
637 : : type(metricrec_type),intent(inout) :: metrec
638 : : type(nlpsprec_type),intent(inout) :: nlrec
639 : : ! arrays
640 : : integer,intent(in) :: ngfftrec(18)
641 : : !Local ---------------------------
642 : : integer :: ii,jj
643 : : character(500) :: msg
644 : : ! *********************************************************************
645 : : !!--Routine for the calcul of the non-local pseudo
646 [ + + + - : 12 : if(any(psps%pspcod/=3) .and. nlrec%nlpsp ) then
- + - - ]
647 : 0 : msg = "The non-local part of psp is used in Recursion only for hgh-psp"
648 : 0 : ABI_WARNING(msg)
649 : 0 : nlrec%nlpsp = .False.
650 [ # # ]: 0 : if (allocated(metrec%gcart)) then
651 : 0 : ABI_FREE(metrec%gcart)
652 : : end if
653 : : end if
654 : :
655 [ + - - + : 6 : if(any(psps%pspcod==3) .and. nlrec%nlpsp) then
+ - - + ]
656 : :
657 : 0 : nlrec%nlpsp = .True.
658 : 0 : nlrec%npsp = psps%npsp
659 [ # # # # ]: 0 : nlrec%lmnmax = count(psps%indlmn(3,:,psps%npsp)/=0)
660 [ # # # # : 0 : ABI_MALLOC(nlrec%mat_exp_psp_nl,(3,3,psps%mpsang,psps%npsp))
# # # # #
# # # # #
# # # # ]
661 [ # # # # : 0 : ABI_MALLOC(nlrec%eival,(3,psps%mpsang,psps%npsp))
# # # # #
# # # # #
# # # # ]
662 [ # # # # : 0 : ABI_MALLOC(nlrec%eivec,(3,3,psps%mpsang,psps%npsp))
# # # # #
# # # #
# ]
663 [ # # # # : 0 : ABI_MALLOC(nlrec%pspinfo,(psps%mpsang,psps%npsp))
# # # # #
# # # # #
# # # # ]
664 [ # # # # : 0 : ABI_MALLOC(nlrec%radii,(psps%mpsang,psps%npsp))
# # # # #
# # # # #
# # # # ]
665 [ # # # # : 0 : ABI_MALLOC(nlrec%indlmn,(6,nlrec%lmnmax,psps%npsp))
# # # # #
# # # # #
# # # # ]
666 [ # # # # : 0 : nlrec%indlmn(:,:,:) = psps%indlmn(:,:nlrec%lmnmax,:)
# # ]
667 [ # # # # : 0 : nlrec%mat_exp_psp_nl(:,:,:,:) = zero
# # # # ]
668 [ # # # # : 0 : nlrec%eivec(:,:,:,:) = zero
# # # # ]
669 [ # # # # : 0 : nlrec%eival(:,:,:) = zero
# # ]
670 [ # # # # ]: 0 : nlrec%radii(:,:) = zero
671 [ # # # # ]: 0 : nlrec%pspinfo(:,:) = 0
672 : :
673 : : !--Get the exponential of the strength times the projectors overlap
674 : : ! of the non-local part of psp(hgh):
675 : : ! h_ij=strength; g_ij=ovelap => (exp(-h.g/temp/4p)-Identity).g^(-1)
676 : : ! And the diagonalisation of the projectors and associated eigenvectors
677 : 0 : call pspnl_hgh_rec(psps,tempe,nlrec,debug)
678 : :
679 [ # # ]: 0 : if(debug)then
680 [ # # ]: 0 : do jj=1,psps%npsp
681 : 0 : write(msg,'(a)')' Exponential matrices:'
682 : 0 : call wrtout(std_out,msg,'COLL')
683 [ # # ]: 0 : do ii=1,psps%mpsang
684 : : write(msg,'(a,i2,a,3f15.10,a,3f15.10,a,3f15.10)')&
685 : 0 : & 'angular moment',ii-1,ch10,&
686 : 0 : & nlrec%mat_exp_psp_nl(1,:,ii,jj),ch10,&
687 : 0 : & nlrec%mat_exp_psp_nl(2,:,ii,jj),ch10,&
688 : 0 : & nlrec%mat_exp_psp_nl(3,:,ii,jj)
689 : 0 : call wrtout(std_out,msg,'COLL')
690 : : end do
691 : : end do
692 : : end if
693 : :
694 : : !--Now it calculates the matrix of the exp(V_NL)
695 : 0 : call pspnl_operat_rec(nlrec,metrec,ngfftrec,debug)
696 : :
697 : : else !--Only local pseudo potentials
698 : 6 : nlrec%nlpsp = .False.
699 : 6 : nlrec%npsp = psps%npsp
700 [ - + - + ]: 6 : ABI_MALLOC(nlrec%mat_exp_psp_nl,(0,0,0,0))
701 [ - + - + ]: 6 : ABI_MALLOC(nlrec%pspinfo,(0,0))
702 [ - + - + ]: 6 : ABI_MALLOC(nlrec%radii,(0,0))
703 [ - + - + ]: 6 : ABI_MALLOC(nlrec%indlmn,(0,0,0))
704 [ - + - + ]: 6 : ABI_MALLOC(nlrec%projec,(0,0,0))
705 : : endif
706 : :
707 : 6 : end subroutine Init_nlpspRec
708 : : !!***
709 : :
710 : : !!****f* m_rec/CleanRec
711 : : !! NAME
712 : : !! CleanRec
713 : : !!
714 : : !! FUNCTION
715 : : !! Deallocate the pointers of rset<recursion_type>=Data type concerning recursion.
716 : : !!
717 : : !! INPUTS
718 : : !! rset<recursion_type>=Data type concerning recursion
719 : : !!
720 : : !! SIDE EFFECTS
721 : : !! All pointers are deallocated.
722 : : !!
723 : : !! SOURCE
724 : :
725 : 6 : subroutine CleanRec(rset)
726 : :
727 : : !Arguments ------------------------------------
728 : : ! scalars
729 : : type(recursion_type),intent(inout) :: rset
730 : : ! arrays
731 : : ! *********************************************************************
732 : :
733 : : ! @recursion_type
734 : :
735 [ + - ]: 6 : ABI_SFREE(rset%ZT_p)
736 [ + - ]: 6 : ABI_SFREE(rset%par%displs)
737 [ + - ]: 6 : ABI_SFREE(rset%par%vcount)
738 [ + - ]: 6 : ABI_SFREE(rset%nl%mat_exp_psp_nl)
739 [ - + ]: 6 : ABI_SFREE(rset%nl%eival)
740 [ - + ]: 6 : ABI_SFREE(rset%nl%eivec)
741 [ + - ]: 6 : ABI_SFREE(rset%nl%pspinfo)
742 [ + - ]: 6 : ABI_SFREE(rset%nl%radii)
743 [ + - ]: 6 : ABI_SFREE(rset%nl%indlmn)
744 [ + - ]: 6 : ABI_SFREE(rset%nl%projec)
745 [ + - ]: 6 : ABI_SFREE(rset%inf%gcart)
746 : :
747 : 6 : call pawfgr_destroy(rset%pawfgr)
748 : :
749 : : ! No is needed deallocate rset%mpi: it is a copy of mpi_enreg which
750 : : ! pointers are deallocated in gstate
751 : :
752 : : #ifdef HAVE_GPU_CUDA
753 : : call CleanRecGPU(rset%GPU,rset%load)
754 : : #endif
755 : :
756 : 6 : end subroutine CleanRec
757 : : !!***
758 : :
759 : : !!****f* m_rec/Calcnrec
760 : : !! NAME
761 : : !! Calcnrec
762 : : !!
763 : : !! FUNCTION
764 : : !! Calculate the new min_nrec.
765 : : !!
766 : : !! INPUTS
767 : : !! rset<recursion_type>=Data type concerning recursion
768 : : !! b2(:,:) recursion coefficients
769 : : !!
770 : : !! OUTPUT
771 : : !! rset%min_nrec is changed
772 : : !!
773 : : !! SOURCE
774 : :
775 : 12 : subroutine Calcnrec(rset,b2)
776 : :
777 : : !Arguments ------------------------------------
778 : : ! scalars
779 : : type(recursion_type),intent(inout) :: rset
780 : : ! arrays
781 : : real(dp), intent(in):: b2(0:rset%min_nrec,1:rset%par%ntranche)
782 : : !Local ----------------------------------------
783 : : ! scalars
784 : : integer :: kk,ii,jj,ierr,loc_nrec
785 : : character(len=500) :: msg
786 : : ! *********************************************************************
787 : : ! @recursion_type
788 : : ! @pawfgr_type
789 : 6 : kk = 1
790 : 6 : loc_nrec = rset%min_nrec
791 [ + + ]: 5190 : do ii=1,rset%par%ntranche
792 : : !--Use to lbound because b2 passed as argument
793 : : ! doesn't have the same bounds as in the calling
794 : : ! subroutine, the +1 because b2(lbound,ii)=1.
795 [ + - ]: 10368 : jj = lbound(b2,dim=1)+1
796 [ + + - + ]: 23631 : do while (b2(jj,ii)>tol10 .and. jj<=rset%min_nrec-1)
797 : 18441 : jj = jj+1
798 : 23625 : kk = max(jj,kk)
799 : : end do
800 : : enddo
801 : 6 : call xmpi_max(kk,rset%min_nrec,rset%mpi%comm_bandfft,ierr)
802 [ + - ]: 6 : rset%min_nrec = rset%min_nrec+1-lbound(b2,dim=1)
803 : :
804 : 6 : write(msg,'(a,i2.2,a9,i2.2)') ' -- nrec adjustement nrec=',loc_nrec,' => nrec=',rset%min_nrec
805 : 6 : call wrtout(std_out,msg,'COLL')
806 [ + - + + ]: 306 : write(msg,'(51a)')' ',('-',ii=1,50)
807 : 6 : call wrtout(std_out,msg,'COLL')
808 : :
809 : 6 : end subroutine Calcnrec
810 : : !!***
811 : :
812 : : !!****f* ABINIT/getngrec
813 : : !! NAME
814 : : !! getngrec
815 : : !!
816 : : !! FUNCTION
817 : : !! This routine computes the fft box for the recursion method, accordingly to the troncation radius.
818 : : !! It is quite similar to getng, but :
819 : : !! - there is no xboxcut and ecut consistency
820 : : !! - ngfft (the initial fft box) is the maximum fft box
821 : : !!
822 : : !! INPUTS
823 : : !! ngfft(18)=non truncated fft box
824 : : !! mgfft=maximum of ngfft(1:3)
825 : : !! inf_rmet=define the infinitesimal metric : rprimd*(transpose(rprimd)), divided by the number of discretisation point
826 : : !! recrcut=truncating
827 : : !! delta=to obtain radius of truncation
828 : : !!
829 : : !! OUTPUT
830 : : !! ngfftrec=truncated fft box
831 : : !! nfftrec= truncated nfft
832 : : !! tronc=True if truncation is made
833 : : !!
834 : : !! SIDE EFFECTS
835 : : !!
836 : : !! SOURCE
837 : :
838 : 6 : subroutine getngrec(ngfft,rmet,ngfftrec,nfftrec,recrcut,delta,tronc)
839 : :
840 : : !Arguments -------------------------------
841 : : !scalars
842 : : real(dp),intent(in) :: recrcut,delta
843 : : integer,intent(out) :: nfftrec
844 : : logical,intent(out) :: tronc
845 : : !arrays
846 : : integer,intent(in) :: ngfft(18)
847 : : real(dp),intent(in) :: rmet(3,3)
848 : : integer,intent(out) :: ngfftrec(18)
849 : :
850 : : !Local variables-------------------------------
851 : : !scalars
852 : : integer :: ii,iimin,index,jj,jjmin,kk,kkmin,largest_ngfftrec,maxpow11,maxpow2
853 : : integer :: maxpow3,maxpow5,maxpow7,mmsrch,plane
854 : : real(dp) :: dsm,dsp,dsqmin,rtroncat
855 : : !arrays
856 : : integer :: get_ngfftrec(3),maxsrch(3),minsrch(3)
857 : 6 : integer,allocatable :: iperm(:),srch(:)
858 : : real(dp) :: tsec(2)
859 : : real(dp) :: inf_rmet(3,3)
860 : : ! *************************************************************************
861 : :
862 : 6 : call timab(602,1,tsec)
863 : :
864 : 6 : ngfftrec(:) = ngfft(:)
865 : :
866 [ + + ]: 6 : if (recrcut>tol14) then !default value dtset%recrcut = zero means no troncation
867 : 1 : rtroncat = recrcut+delta
868 [ + + ]: 4 : get_ngfftrec(:)=1
869 : 1 : plane = 1
870 : :
871 [ + + ]: 4 : do ii=1,3
872 [ + + ]: 13 : inf_rmet(ii,:) = rmet(ii,:)/(real(ngfft(1:3)*ngfft(ii),dp))
873 : : end do
874 : :
875 : :
876 : : ! minimum value of ngfftrec
877 [ + + ]: 4 : do ii = 1,3
878 [ + - ]: 3 : ngfftrec(ii)=floor(2*rtroncat/sqrt(inf_rmet(ii,ii)))+1 !minimum value
879 [ - + ]: 4 : if(ngfftrec(ii)>=ngfft(ii))then
880 : 0 : ngfftrec(ii)=ngfft(ii)
881 : 0 : get_ngfftrec(ii)=0
882 : : end if
883 : : end do
884 : :
885 : :
886 [ + + + - ]: 4 : if(sum(get_ngfftrec)/=0)then
887 [ + + ]: 4 : largest_ngfftrec=maxval(ngfft(1:3))
888 : 1 : maxpow2=int(log(largest_ngfftrec+0.5d0)/log(two))
889 : 1 : maxpow3=int(log(largest_ngfftrec+0.5d0)/log(three))
890 : 1 : maxpow5=int(log(largest_ngfftrec+0.5d0)/log(five))
891 : 1 : maxpow7=0
892 : 1 : maxpow11=0
893 : 1 : mmsrch=(maxpow2+1)*(maxpow3+1)*(maxpow5+1)*(maxpow7+1)*(maxpow11+1)
894 [ - + + - : 3 : ABI_MALLOC(srch,(mmsrch))
+ - + - -
+ - + ]
895 [ - + + - : 2 : ABI_MALLOC(iperm,(mmsrch))
- + - + ]
896 : : ! Factors of 2
897 : 1 : srch(1)=1
898 [ + + ]: 4 : do ii=1,maxpow2
899 : 4 : srch(ii+1)=srch(ii)*2
900 : : end do
901 : : ! Factors of 3
902 : 1 : index=maxpow2+1
903 [ + - ]: 1 : if(maxpow3>0)then
904 [ + + ]: 3 : do ii=1,maxpow3
905 [ + - + + : 19 : srch(1+ii*index:(ii+1)*index)=3*srch(1+(ii-1)*index:ii*index)
+ + ]
906 : : end do
907 : : end if
908 : : ! Factors of 5
909 : 1 : index=(maxpow3+1)*index
910 [ + - ]: 1 : if(maxpow5>0)then
911 [ + + ]: 2 : do ii=1,maxpow5
912 [ + - + + : 26 : srch(1+ii*index:(ii+1)*index)=5*srch(1+(ii-1)*index:ii*index)
+ + ]
913 : : end do
914 : : end if
915 : : ! Factors of 7
916 : : index=(maxpow5+1)*index
917 : : if(maxpow7>0)then
918 : : do ii=1,maxpow7
919 : : srch(1+ii*index:(ii+1)*index)=7*srch(1+(ii-1)*index:ii*index)
920 : : end do
921 : : end if
922 : : ! Factors of 11
923 : 1 : index=(maxpow7+1)*index
924 : : if(maxpow11>0)then
925 : : do ii=1,maxpow11
926 : : srch(1+ii*index:(ii+1)*index)=11*srch(1+(ii-1)*index:ii*index)
927 : : end do
928 : : end if
929 : : ! srch is the set of allowed ngfftrec values
930 : :
931 : 1 : call sort_int(mmsrch,srch,iperm)
932 [ - + ]: 1 : ABI_FREE(iperm)
933 : :
934 [ + + ]: 4 : do ii=1,3
935 [ + - ]: 3 : if(get_ngfftrec(ii)==1)then
936 [ + - ]: 12 : do jj=1,mmsrch
937 [ + + ]: 12 : if(srch(jj)>=ngfftrec(ii))then
938 : 3 : minsrch(ii)=jj
939 : 3 : ngfftrec(ii)=srch(jj)
940 : 3 : exit
941 : : end if
942 : : end do
943 [ + - ]: 24 : do jj=minsrch(ii),mmsrch
944 [ + + ]: 24 : if(srch(jj)>ngfft(ii))then
945 : : ! since ngfftrec(ii)<ngfft(ii) for get_ngfftrec(ii)==1,
946 : : ! and srch(mmsrch)maxval(ngfft(1:3)),
947 : : ! that will appens in the range minsrch(ii),mmsrch
948 : 3 : maxsrch(ii)=jj-1
949 : 3 : exit
950 : : end if
951 : : end do
952 : : end if
953 : : ! since ngfft(ii) is in srch, we have here srch(maxsrch(ii))=ngfft(ii)
954 : : ! minsrch(ii), maxsrch(ii) is the range of index of srch in which we can
955 : : ! search ngfftrec(ii)
956 : :
957 [ - + ]: 4 : if(ngfftrec(ii)>=ngfft(ii))then
958 : 0 : ngfftrec(ii)=ngfft(ii)
959 : 0 : get_ngfftrec(ii)=0
960 : : end if
961 : : end do
962 : : end if
963 : :
964 : : ! verify that the entiere truncation sphere is in the fft box ;
965 : : ! but only in the dimension in which we do not consider the entiere fft box
966 [ + + + - ]: 4 : do while(sum(get_ngfftrec)/=0) !again...
967 : :
968 : : ! determining the minimum distance between 0 and the boundary
969 : : ! of the fft box
970 : : ! quite similar to the subroutine "bound", but only over the plane which
971 : : ! are not the whole fft box
972 : 1 : dsqmin=dsq_rec(ngfftrec(1)/2,-ngfftrec(2)/2,-ngfftrec(3)/2,inf_rmet)+0.01d0
973 : :
974 [ + - ]: 1 : if(get_ngfftrec(1)/=0)then
975 : : ! look at +/- g1 planes:
976 [ + + ]: 6 : do jj=-ngfftrec(2)/2,ngfftrec(2)/2
977 [ + + ]: 31 : do kk=-ngfftrec(3)/2,ngfftrec(3)/2
978 : 25 : dsp = dsq_rec(ngfftrec(1)/2, jj, kk,inf_rmet)
979 : 25 : dsm = dsq_rec( - ngfftrec(1)/2, jj, kk,inf_rmet)
980 [ + + ]: 25 : if (dsp<dsqmin) then
981 : 6 : dsqmin = dsp
982 : 6 : iimin = ngfftrec(1)/2
983 : 6 : jjmin = jj
984 : 6 : kkmin = kk
985 : 6 : plane=1
986 : : end if
987 [ - + ]: 30 : if (dsm<dsqmin) then
988 : 0 : dsqmin = dsm
989 : 0 : iimin = - ngfftrec(1)/2
990 : 0 : jjmin = jj
991 : 0 : kkmin = kk
992 : 0 : plane=1
993 : : end if
994 : : end do
995 : : end do
996 : : end if
997 : :
998 [ + - ]: 1 : if(get_ngfftrec(2)/=0)then
999 : : ! +/- g2 planes:
1000 [ + + ]: 6 : do ii=-ngfftrec(1)/2,ngfftrec(1)/2
1001 [ + + ]: 31 : do kk=-ngfftrec(3)/2,ngfftrec(3)/2
1002 : 25 : dsp = dsq_rec(ii,ngfftrec(2)/2,kk,inf_rmet)
1003 : 25 : dsm = dsq_rec(ii,-ngfftrec(2)/2,kk,inf_rmet)
1004 [ - + ]: 25 : if (dsp<dsqmin) then
1005 : 0 : dsqmin = dsp
1006 : 0 : iimin = ii
1007 : 0 : jjmin = ngfftrec(2)/2
1008 : 0 : kkmin = kk
1009 : 0 : plane=2
1010 : : end if
1011 [ - + ]: 30 : if (dsm<dsqmin) then
1012 : 0 : dsqmin = dsm
1013 : 0 : iimin = ii
1014 : 0 : jjmin = - ngfftrec(2)/2
1015 : 0 : kkmin = kk
1016 : 0 : plane=2
1017 : : end if
1018 : : end do
1019 : : end do
1020 : : end if
1021 : :
1022 [ + - ]: 1 : if(get_ngfftrec(3)/=0)then
1023 : : ! +/- g3 planes:
1024 [ + + ]: 6 : do ii=-ngfftrec(1)/2,ngfftrec(1)/2
1025 [ + + ]: 31 : do jj=-ngfftrec(2)/2,ngfftrec(2)/2
1026 : 25 : dsp = dsq_rec(ii,jj,ngfftrec(3)/2,inf_rmet)
1027 : 25 : dsm = dsq_rec(ii,jj,-ngfftrec(3)/2,inf_rmet)
1028 [ - + ]: 25 : if (dsp<dsqmin) then
1029 : 0 : dsqmin = dsp
1030 : 0 : iimin = ii
1031 : 0 : jjmin = jj
1032 : 0 : kkmin = ngfftrec(3)/2
1033 : 0 : plane=3
1034 : : end if
1035 [ - + ]: 30 : if (dsm<dsqmin) then
1036 : 0 : dsqmin = dsm
1037 : 0 : iimin = ii
1038 : 0 : jjmin = jj
1039 : 0 : kkmin = - ngfftrec(3)/2
1040 : 0 : plane=3
1041 : : end if
1042 : : end do
1043 : : end do
1044 : : end if
1045 : :
1046 [ - + ]: 1 : if(dsqmin>=rtroncat)then
1047 : : get_ngfftrec=0
1048 : : exit
1049 : : end if
1050 : :
1051 : : ! Fix nearest boundary
1052 [ # # ]: 0 : do ii=minsrch(plane),maxsrch(plane)
1053 [ # # ]: 0 : if (srch(ii)>=ngfftrec(plane)) then
1054 : : ! redefine ngfft(plane) to next higher choice
1055 : 0 : ngfftrec(plane)=srch(ii+1)
1056 : : ! verify if we cover the whole box
1057 [ # # ]: 0 : if(ngfftrec(plane)>=ngfft(plane))then
1058 : 0 : ngfftrec(plane)=ngfft(plane)
1059 : 0 : get_ngfftrec(plane)=0
1060 : : end if
1061 : : ! Exit the loop over ii
1062 : : exit
1063 : : end if
1064 : : end do
1065 : :
1066 : : end do
1067 : :
1068 [ + - ]: 1 : if (allocated(srch)) then
1069 : 1 : ABI_FREE(srch)
1070 : : end if
1071 : :
1072 : : ! if(mod(ngfftrec(1),16)/=0) then
1073 : : ! ngfftrec(1) = ngfftrec(1)+(16-mod(ngfftrec(1),16))
1074 : : ! ngfftrec(2:3) = ngfftrec(1)
1075 : : ! endif
1076 : :
1077 : 1 : ngfftrec(4)=2*(ngfftrec(1)/2)+1
1078 : 1 : ngfftrec(5)=2*(ngfftrec(2)/2)+1
1079 : 1 : ngfftrec(6)=ngfftrec(3)
1080 : :
1081 : : ! --algorithm
1082 : 1 : ngfftrec(7)=ngfft(7) ! to be improved for a better non-parallel algorithm - here it is automatically 401
1083 : 1 : ngfftrec(8)=ngfft(8)
1084 : :
1085 : : end if
1086 : :
1087 : : !--For now, recursion method doesn't use paralelism on FFT - which would require a great number of processors
1088 [ + + ]: 24 : nfftrec = product(ngfftrec(1:3))
1089 [ + + ]: 24 : ngfftrec(9:11) = (/0,1,0/) !--(/ paral, nproc, %me \)
1090 [ + + ]: 18 : ngfftrec(12:13) = ngfftrec(2:3) ! n2proc ! n3proc
1091 : :
1092 [ + + + + ]: 9 : tronc = all(ngfftrec(:3)/=ngfft(:3))
1093 : 6 : call timab(602,2,tsec)
1094 : :
1095 : : contains
1096 : :
1097 : 151 : function dsq_rec(ii,jj,kk,inf_rmet)
1098 : :
1099 : : real(dp) :: dsq_rec
1100 : : integer,intent(in) :: ii,jj,kk
1101 : : real(dp),intent(in) :: inf_rmet(3,3)
1102 : : dsq_rec=sqrt(&
1103 : : & inf_rmet(1,1)*dble(ii**2)&
1104 : : & +inf_rmet(2,2)*dble(jj**2)&
1105 : : & +inf_rmet(3,3)*dble(kk**2)&
1106 : : & +two*(inf_rmet(1,2)*dble(ii*jj)&
1107 : : & +inf_rmet(2,3)*dble(jj*kk)&
1108 : 151 : & +inf_rmet(3,1)*dble(kk*ii)))
1109 : 151 : end function dsq_rec
1110 : :
1111 : :
1112 : : end subroutine getngrec
1113 : : !!***
1114 : :
1115 : : !!****f* ABINIT/pspnl_operat_rec
1116 : : !! NAME
1117 : : !! pspnl_operat_rec
1118 : : !!
1119 : : !! FUNCTION
1120 : : !! It calculates the non-local projectors used in recursion for any psp non-local:
1121 : : !! The nl interaction in recursion is $$exp{-V_{NL}/beta}=\sum_A\sum_{lm}
1122 : : !! \sum{ij}Y_{lm}(\hat{r-R_A}')f^l_i(r-R_A)D^l_{i,j}Y_{lm}(\hat{r-R_A})f^l_j{r-R_A}$$
1123 : : !! where $D^_{i,j}$ is a matrix previously (see pspnl_operat_rec).
1124 : : !! In this routine the projectors $Y_{lm}(\hat{r-R_A}')f^l_i(r-R_A)$
1125 : : !! are calculated. So an array of dimensions
1126 : : !! rset%nl%projec(nfftrec,lmnmax,nlrec%npsp)
1127 : : !!
1128 : : !! INPUTS
1129 : : !! metrec<metricrec_type>=contains information concerning metric in
1130 : : !! recursion: grid_step, metric, infinitesimal volume
1131 : : !! ngfftrec(18)=is the ngfft grid (truncated if different from ngfft) of recursion
1132 : : !! debug=debug variable
1133 : : !!
1134 : : !!
1135 : : !! OUTPUT
1136 : : !! nlrec<nlpsprec_type>%projec= array containig the projectors on the real grid
1137 : : !! nlrec<nlpsprec_type>%intlen= integer linear size of the non-local grid
1138 : : !!
1139 : : !! SIDE EFFECTS
1140 : : !! nlrec<nlpsprec_type> data set of non-local pseudo for recursion
1141 : : !! The better Interaction length (Intlen) is also calculated and printed but
1142 : : !! recursion use intlen=ngfftrec/2
1143 : : !!
1144 : : !! NOTES
1145 : : !!
1146 : : !! SOURCE
1147 : :
1148 : :
1149 : 0 : subroutine pspnl_operat_rec(nlrec,metrec,ngfftrec,debug)
1150 : :
1151 : : !Arguments ------------------------------------
1152 : : !scalars
1153 : : logical,intent(in) :: debug
1154 : : type(metricrec_type),intent(in) ::metrec
1155 : : type(nlpsprec_type),intent(inout) :: nlrec
1156 : : !arrays
1157 : : integer,intent(in) :: ngfftrec(18)
1158 : : !Local variables-------------------------------
1159 : : integer :: ii,intlen
1160 : : integer :: iangol,ipsp,iproj
1161 : : integer :: mpsang,jj,kk,rr
1162 : : integer :: nfftrec
1163 : : integer :: ilmn,il,ilm,in,lmnmax
1164 : : real(dp) :: raggio,rloc,denom,step
1165 : : real(dp) :: delta_out,partial,err
1166 : : character(len=500) :: msg
1167 : : real(dp) :: part_sum(3)
1168 : : real(dp) :: ylmr_gr_dm(0,0,0)
1169 : 0 : real(dp),allocatable :: ylmr(:,:),proj_arr(:,:,:)
1170 : 0 : real(dp),allocatable :: radloc(:,:),nrm(:)
1171 : :
1172 : : ! *************************************************************************
1173 : :
1174 [ # # ]: 0 : if(debug)then
1175 [ # # # # ]: 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' pspnl_operat_rec : enter '
1176 : 0 : call wrtout(std_out,msg,'PERS')
1177 : : end if
1178 : :
1179 : : !#####################################################################
1180 : : !--CALCULATE THE (SEMI-)MAXIMUM INTERVAL WHERE ALL THE PROJECTORS ARE
1181 : : !DIFFERENT TO ZERO.
1182 : : !--For any pseudo potential:
1183 : 0 : delta_out = zero
1184 : 0 : step = metrec%tr(1)*half !--Scanning step= grid step/2
1185 : :
1186 : :
1187 [ # # ]: 0 : do ipsp = 1, nlrec%npsp !--Loop on the pseudos
1188 : :
1189 : : ! --For any angular moment:
1190 [ # # # # ]: 0 : do iangol = 0,maxval(nlrec%indlmn(1,:,ipsp)) !--Loop on the angular moment
1191 : 0 : rloc = nlrec%radii(iangol+1,ipsp) !--Local radius
1192 : :
1193 : : ! --For any projector
1194 [ # # ]: 0 : do iproj = 1,nlrec%pspinfo(iangol+1,ipsp)
1195 : : ! --Starting point to searching when the projector goes to zero.
1196 : : ! this correspond to twice the radius wher the projector has its maximum
1197 : 0 : raggio = two*sqrt(real(-2+2*iproj+iangol,dp))*rloc
1198 : : ! --Caculate the gamma func at the denominator
1199 : 0 : call gamma_function(real(iangol+2*iproj,dp)-half,denom)
1200 : : ! --Find the zero
1201 : : ! --The following while cycle should be replaced by a bisection
1202 : : ! --method. Bucause this is calculated only 1 time it is not very
1203 : : ! important.
1204 : 0 : err = one
1205 : 0 : ii=0
1206 : : ! tolloc = 1.d0*abs(minval(nlrec%mat_exp_psp_nl(:nlrec%pspinfo(iangol+1,ipsp),:nlrec%pspinfo(iangol+1,ipsp),iangol+1,ipsp)))
1207 [ # # ]: 0 : do while(abs(err)>1.d-2)
1208 : 0 : raggio = raggio + step
1209 : 0 : err = project_prec(raggio,iproj,iangol,rloc)/sqrt(denom)
1210 : 0 : ii = ii+1
1211 : : end do
1212 : 0 : write(std_out,*)'local delta',raggio,ii
1213 [ # # # # : 0 : delta_out=maxval((/ delta_out,raggio /))
# # ]
1214 : : end do !end loop on projectors
1215 : :
1216 : : end do !enddo on angular moment
1217 : : end do !enddo on pseudos
1218 : :
1219 : : !--CALCULATE how many grid steps correspond to delta_out
1220 : 0 : intlen = int(delta_out/metrec%tr(1))
1221 : : !--I want that intlen is odd
1222 [ # # ]: 0 : if(mod(intlen,2)==0) intlen = intlen+1
1223 : :
1224 : 0 : write(msg,'(2a,i3,a)') ch10,' Interac. length of non-local psp(grid steps)=',intlen,ch10
1225 : 0 : call wrtout(std_out,msg,'COLL')
1226 : : !#####################################################################
1227 : :
1228 : : !--Initialisation
1229 [ # # ]: 0 : nfftrec = product(ngfftrec(1:3))
1230 : 0 : lmnmax = nlrec%lmnmax
1231 : 0 : intlen = ngfftrec(1)/2
1232 : 0 : nlrec%intlen = intlen !--Setted in recursion variables
1233 : :
1234 : : !#####################################################################
1235 : : !--CALCULATE E(q,q')
1236 : : !--Cration of the exponential*projectors*ylm matrix
1237 : :
1238 : : !--Initialisation
1239 [ # # # # : 0 : ABI_MALLOC(nlrec%projec,(nfftrec,lmnmax,nlrec%npsp))
# # # # #
# # # # #
# # # # #
# # # ]
1240 [ # # # # : 0 : nlrec%projec = zero
# # ]
1241 [ # # # # : 0 : ABI_MALLOC(radloc,(3,nfftrec))
# # # # #
# # # ]
1242 [ # # # # ]: 0 : radloc = zero
1243 [ # # # # : 0 : ABI_MALLOC(nrm,(nfftrec))
# # # # #
# # # ]
1244 [ # # ]: 0 : nrm = zero
1245 : :
1246 : : !--Loop on pseudo types
1247 [ # # ]: 0 : pseudodo: do ipsp = 1, nlrec%npsp
1248 : : ! --Control if the psp is non-local, else continue
1249 [ # # # # : 0 : if(all(nlrec%pspinfo(:,ipsp)==0)) cycle
# # ]
1250 : : ! --Vector which stores localy the upper part of symmetrical
1251 : : ! matrix of the exponential of the non-local operator
1252 [ # # ]: 0 : mpsang = maxval(nlrec%indlmn(1,:,ipsp))+1
1253 [ # # # # : 0 : ABI_MALLOC(proj_arr,(nfftrec,maxval(nlrec%pspinfo(:,ipsp)),mpsang))
# # # # #
# # # # #
# # # # #
# # # ]
1254 [ # # # # : 0 : ABI_MALLOC(ylmr,(mpsang*mpsang,nfftrec))
# # # # #
# # # # #
# # ]
1255 [ # # # # : 0 : proj_arr = zero
# # ]
1256 [ # # # # ]: 0 : ylmr = zero
1257 : :
1258 : : ! !debug
1259 : : ! write(std_out,*)'mpsang,proj num',mpsang,maxval(nlrec%pspinfo(:,ipsp))
1260 : : ! !enddebug
1261 : :
1262 : : ! --Calculate the projctors
1263 [ # # ]: 0 : do iangol = 0,mpsang-1
1264 : 0 : rloc = nlrec%radii(iangol+1,ipsp)
1265 [ # # ]: 0 : do iproj = 1,nlrec%pspinfo(iangol+1,ipsp)
1266 : 0 : call gamma_function(real(iangol+2*iproj,dp)-half,denom)
1267 : 0 : denom = one/sqrt(denom)
1268 [ # # ]: 0 : do ii = 0,ngfftrec(1)-1 !--3-loop on coordinates
1269 [ # # ]: 0 : do jj = 0,ngfftrec(2)-1
1270 [ # # ]: 0 : do kk = 0,ngfftrec(3)-1
1271 : : ! --Calculate the radii
1272 [ # # ]: 0 : part_sum(:) = real((/ ii,jj,kk /)-intlen,dp)*(metrec%tr)
1273 : 0 : rr = 1+ii+(jj+kk*ngfftrec(2))*ngfftrec(3)
1274 [ # # ]: 0 : radloc(:,rr) = part_sum
1275 [ # # ]: 0 : nrm(rr) = sqrt(sum(part_sum(:)**two))
1276 : 0 : partial = project_prec(nrm(rr),iproj,iangol,rloc)*denom
1277 [ # # ]: 0 : if(abs(partial)>tol12 ) proj_arr(rr,iproj,iangol+1) = partial
1278 : : end do
1279 : : end do
1280 : : end do !--End 3-loop on coordinates
1281 : : end do
1282 : : end do
1283 : :
1284 : :
1285 : : ! -------------------------------------------------------------
1286 : : ! --Calculate the spherical harmonics (Verified: it works well)
1287 : 0 : call initylmr(mpsang,1,nfftrec,nrm(:),1,radloc(:,:),ylmr(:,:),ylmr_gr_dm)
1288 : : ! -------------------------------------------------------------
1289 : :
1290 : :
1291 [ # # ]: 0 : do ilmn = 1,lmnmax
1292 : 0 : ilm = nlrec%indlmn(4,ilmn,ipsp)
1293 : 0 : il = nlrec%indlmn(1,ilmn,ipsp)+1
1294 : 0 : in = nlrec%indlmn(3,ilmn,ipsp)
1295 : 0 : write(msg,'(2a,i3,2i2)')ch10,'lm,l,n',ilm,il,in
1296 : 0 : call wrtout(std_out,msg,'COLL')
1297 : :
1298 [ # # ]: 0 : nlrec%projec(:,ilmn,ipsp) = ylmr(ilm,:)*proj_arr(:,in,il)
1299 : : end do
1300 : :
1301 [ # # ]: 0 : ABI_FREE(ylmr)
1302 [ # # ]: 0 : ABI_FREE(proj_arr)
1303 : : end do pseudodo !--end loop on pseudo types
1304 : :
1305 : :
1306 [ # # ]: 0 : ABI_FREE(radloc)
1307 [ # # ]: 0 : ABI_FREE(nrm)
1308 : :
1309 [ # # ]: 0 : if(debug)then
1310 [ # # # # ]: 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' pspnl_operat_rec : exit '
1311 : 0 : call wrtout(std_out,msg,'PERS')
1312 : : end if
1313 : :
1314 : : contains
1315 : :
1316 : 0 : function project_prec(raggio,iproj,iangol,rloc)
1317 : : !--Analytical expression of the projectors in hgh-pspeudopotential
1318 : : !--The gamma function at denominator is missing
1319 : : real(dp) :: project_prec
1320 : : integer,intent(in) :: iproj,iangol
1321 : : real(dp),intent(in) :: raggio,rloc
1322 : :
1323 : : project_prec=sqrt2*(raggio/rloc)**real((iangol+2*(iproj-1)),dp)*&
1324 : 0 : & exp(-((raggio/rloc)**two)*half)/rloc**onehalf
1325 : 0 : end function project_prec
1326 : :
1327 : : end subroutine pspnl_operat_rec
1328 : : !!***
1329 : :
1330 : : !!****f* ABINIT/pspnl_hgh_rec
1331 : : !! NAME
1332 : : !! pspnl_hgh_rec
1333 : : !!
1334 : : !! FUNCTION
1335 : : !! This routine computes the matrices S_kk'^{l,A} of the projectors
1336 : : !! (it is the exponential of the overlap matrix). It coorresponds to the matrix:
1337 : : !! $$\left[(U_l)^{-1}*Exp(-temperature D_l )*U_l* (g_l)^{-1} -Identity\right]_kk'
1338 : : !! where (U_l)^-1* D_l* U_l = h^lg_l.
1339 : : !! $g_l = <f^l_k|f^l_{k'}>$ is the overlap matrix between projectors
1340 : : !! and $h^l_{kk'}$ is the strength matrix of the projectors.
1341 : : !! It calulates also the strength eigenvalues and eigenvectors of $h$,
1342 : : !! used in the calculus of non-local energy
1343 : : !!
1344 : : !! INPUTS
1345 : : !! temperature=4*rtrotter/beta=4*rtrotter*tsmear: the effective temp. in recursion
1346 : : !! psps <type(pseudopotential_type)>=variables related to pseudo-potentials
1347 : : !! debug=debug variable
1348 : : !!
1349 : : !! OUTPUT
1350 : : !!
1351 : : !! nlrec%mat_exp_psp_nl=the matrix of the exponential of the projectors:
1352 : : !! for any psp, for any angular moment:
1353 : : !! h_ij=strength; g_ij=ovelap => exp(-h.g/temp/4p).g^(-1)
1354 : : !! nlrec%radii=Local radii of nl psp
1355 : : !! nlrec%pspinfo(:,:) for any typat: (momang,typat)=number of projectors
1356 : : !! nlrec%eival(:,:,:) for any psp, any momang, the eigenvalues of the
1357 : : !! strength matrix H: eival(:,mang,psp)
1358 : : !! nlrec%eivec(:,:,:,:)for any psp, any momang, the eigenvectors of the
1359 : : !! strength matrix H: eivec(:,:,mang,psp)
1360 : : !!
1361 : : !! SIDE EFFECTS
1362 : : !!
1363 : : !! SOURCE
1364 : :
1365 : 0 : subroutine pspnl_hgh_rec(psps,temperature,nlrec,debug)
1366 : :
1367 : : use m_linalg_interfaces
1368 : :
1369 : : !Arguments -----------------------------------
1370 : : !scalars
1371 : : real(dp),intent(in) :: temperature
1372 : : logical,intent(in) :: debug
1373 : : type(pseudopotential_type),intent(in) :: psps
1374 : : type(nlpsprec_type),intent(inout) :: nlrec
1375 : : !arrays
1376 : : !Local variables-------------------------------
1377 : : !scalars
1378 : : integer,parameter :: maxsize=3
1379 : : integer,parameter :: lwork=(1+32)*maxsize
1380 : : integer :: iangol,ipseudo,info,nproj
1381 : : integer :: g_mat_size,ii,nproj2
1382 : : real(dp) :: denom_1,denom_2,tot_proj
1383 : : character(len=500) :: msg
1384 : : !arrays
1385 : : integer :: ipvt(1)
1386 : : !real(dp) :: rwork(2*maxsize)
1387 : : real(dp) :: h_mat_init(3,3), rework(lwork)
1388 : 0 : real(dp), allocatable :: g_mat(:,:),h_mat(:,:),eig_val_h(:)
1389 : 0 : real(dp), allocatable :: identity(:,:),inv_g_mat(:,:),u_mat(:,:)
1390 : 0 : complex(dp),allocatable :: hg_mat(:,:)
1391 : : ! *************************************************************************
1392 : :
1393 [ # # ]: 0 : if(debug)then
1394 [ # # # # ]: 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' pspnl_hgh_rec : enter '
1395 : 0 : call wrtout(std_out,msg,'COLL')
1396 : : end if
1397 : :
1398 : : !--For any pseudo potential:
1399 [ # # ]: 0 : do ipseudo = 1, psps%npsp !--Loop on the pseudos
1400 [ # # # # ]: 0 : write(msg,'(a,80a)')' pseudo file',('-',ii=1,10)
1401 : 0 : call wrtout(std_out,msg,'COLL')
1402 : 0 : write(msg,'(a)') psps%filpsp(ipseudo)
1403 : 0 : call wrtout(std_out,msg,'COLL')
1404 : :
1405 : : ! --For any angular moment:
1406 [ # # ]: 0 : do iangol = 0,psps%mpsang-1 !--Loop on the angular moment
1407 : :
1408 : : ! --Local radius
1409 : 0 : nlrec%radii(iangol+1,ipseudo) = psps%gth_params%psppar(iangol+1,0,ipseudo)
1410 : :
1411 : : ! --Strenghts of non-local projectors (matrix h)
1412 : : ! --Diagonal part:
1413 : 0 : h_mat_init = zero
1414 : 0 : h_mat_init(1,1) = psps%gth_params%psppar(iangol+1,1,ipseudo)
1415 : 0 : h_mat_init(2,2) = psps%gth_params%psppar(iangol+1,2,ipseudo)
1416 : 0 : h_mat_init(3,3) = psps%gth_params%psppar(iangol+1,3,ipseudo)
1417 : : ! --Out-diagonal part
1418 : : ! --Depending on angular moment the projectors
1419 : : ! strength is calculated differently
1420 : 0 : select case(iangol)
1421 : : case(0)
1422 : 0 : h_mat_init(1,2) = -half*sqrt(3.d0/5.d0)*h_mat_init(2,2)
1423 : 0 : h_mat_init(1,3) = half*sqrt(5.d0/21.d0)*h_mat_init(3,3)
1424 : 0 : h_mat_init(2,3) = -half*sqrt(100.d0/63.d0)*h_mat_init(3,3)
1425 : : case(1)
1426 : 0 : h_mat_init(1,2) = -half*sqrt(5.d0/7.d0)*h_mat_init(2,2)
1427 : 0 : h_mat_init(1,3) = sixth*sqrt(35.d0/11.d0)*h_mat_init(3,3)
1428 : 0 : h_mat_init(2,3) = -14.d0/six/sqrt(11.d0) *h_mat_init(3,3)
1429 : : case(2)
1430 : 0 : h_mat_init(1,2) = -half*sqrt(7.d0/9.d0)*h_mat_init(2,2)
1431 : 0 : h_mat_init(1,3) = half*sqrt(63.d0/143.d0)*h_mat_init(3,3)
1432 : 0 : h_mat_init(2,3) = -nine/sqrt(143.d0)*h_mat_init(3,3)
1433 : : case(3)
1434 : 0 : h_mat_init(1,2) = zero; h_mat_init(1,3) = zero; h_mat_init(2,3) = zero;
1435 : : case default
1436 : 0 : write(msg,'(a)')' error angular: moment component'
1437 [ # # # # : 0 : call wrtout(std_out,msg,'COLL')
# ]
1438 : : end select
1439 : :
1440 : :
1441 : :
1442 : : ! --Real dimensions of projectors.
1443 [ # # # # ]: 0 : g_mat_size = count(abs((/ (h_mat_init(ii,ii),ii=1,3) /))>1.d-8)
1444 : 0 : nlrec%pspinfo(iangol+1,ipseudo) = g_mat_size
1445 : 0 : write(msg,'(a,i2,a,i2)')' ang. moment=',iangol,', N projectors=',g_mat_size
1446 : 0 : call wrtout(std_out,msg,'COLL')
1447 [ # # ]: 0 : if (g_mat_size>0) then
1448 : : ! --Identity matrix
1449 [ # # # # : 0 : ABI_MALLOC(identity,(g_mat_size,g_mat_size))
# # # # #
# # # # #
# # ]
1450 : 0 : call set2unit(identity)
1451 : : ! identity = zero
1452 : : ! identity(:,1) = one
1453 : : ! identity(:,:) = cshift(array=identity,shift=(/ (-ii,ii=0,g_mat_size) /), dim=2 )
1454 : :
1455 : :
1456 : : ! ############## CALCULOUS OF THE EIGEN_SPACE OF THE PROJECTORS STRENGTHS ##################
1457 : : ! --Inverse of the matrix h
1458 [ # # # # : 0 : ABI_MALLOC(eig_val_h,(g_mat_size))
# # # # #
# # # ]
1459 [ # # # # : 0 : ABI_MALLOC(u_mat,(g_mat_size,g_mat_size))
# # # # #
# # # ]
1460 : : ! --u-mat will contain the eigenvectors of h_mat_init
1461 [ # # # # : 0 : u_mat = h_mat_init(:g_mat_size,:g_mat_size)
# # ]
1462 : :
1463 : : ! write(std_out,*)'hmat_init'
1464 : : ! do ii=1,g_mat_size
1465 : : ! write(std_out,*)h_mat_init(ii,:)
1466 : : ! end do
1467 : 0 : call DSYEV('v','u',g_mat_size,u_mat,g_mat_size,eig_val_h,rework,lwork,info)
1468 : :
1469 : : ! --THE DIAGONAL MATRIX IS GIVEN BY D=U^t.H.U
1470 : : ! (eival=transpose(eivec).h_mat_init.eivec)
1471 : 0 : write(msg,'(a,3d10.3)')' eigenvalues=',eig_val_h
1472 : 0 : call wrtout(std_out,msg,'COLL')
1473 : : ! write(std_out,*)'autovec';write(std_out,*)u_mat
1474 : :
1475 [ # # ]: 0 : nlrec%eival(:g_mat_size,1+iangol,ipseudo) = eig_val_h
1476 [ # # # # ]: 0 : nlrec%eivec(:g_mat_size,:g_mat_size,1+iangol,ipseudo) = u_mat
1477 [ # # ]: 0 : ABI_FREE(eig_val_h)
1478 [ # # ]: 0 : ABI_FREE(u_mat)
1479 : :
1480 : : ! ##########END CALCULOUS OF THE EIGEN_SPACE OF THE PROJECTORS STRENGTHS ##################
1481 : :
1482 [ # # # # : 0 : ABI_MALLOC(g_mat,(g_mat_size,g_mat_size))
# # # # #
# # # # #
# # # # ]
1483 [ # # # # : 0 : ABI_MALLOC(inv_g_mat,(g_mat_size,g_mat_size))
# # # # #
# # # #
# ]
1484 [ # # # # : 0 : ABI_MALLOC(h_mat,(g_mat_size,g_mat_size))
# # # # #
# # # #
# ]
1485 [ # # # # : 0 : ABI_MALLOC(hg_mat,(g_mat_size,g_mat_size))
# # # # #
# # # # #
# # # # ]
1486 : :
1487 [ # # # # ]: 0 : g_mat(:,:) = one
1488 [ # # # # ]: 0 : h_mat(:,:) = zero
1489 [ # # # # ]: 0 : h_mat(:,:) = h_mat_init(:g_mat_size,:g_mat_size)
1490 : :
1491 : : ! -------------------------------------------------------
1492 : : ! --Matrix of the overlap between projetors (matrix g)
1493 : : ! and the h matrix of strength
1494 [ # # ]: 0 : do nproj = 1,g_mat_size-1
1495 [ # # ]: 0 : do nproj2 = 1+nproj,g_mat_size
1496 : : tot_proj = zero
1497 : : ! --Analytic value of overlap
1498 : : ! g_ij=Gamma[-1/2+i+j+l]/Sqrt(Gamma[-1/2+i+iangol]*Gamma[-1/2+j+iangol])
1499 : 0 : call gamma_function(-half+real(nproj+nproj2+iangol,dp),tot_proj)
1500 : 0 : call gamma_function(-half+real(iangol+2*nproj,dp),denom_1)
1501 : 0 : call gamma_function(-half+real(iangol+2*nproj2,dp),denom_2)
1502 : :
1503 : 0 : g_mat(nproj,nproj2) = tot_proj/sqrt(denom_1*denom_2)
1504 : 0 : g_mat(nproj2,nproj) = g_mat(nproj,nproj2)
1505 : :
1506 : 0 : h_mat(nproj,nproj2) = h_mat_init(nproj,nproj2)
1507 : 0 : h_mat(nproj2,nproj) = h_mat_init(nproj,nproj2)
1508 : : end do
1509 : : end do
1510 : :
1511 : : ! --Inverse of the overlap matrix g
1512 [ # # # # : 0 : inv_g_mat = g_mat
# # ]
1513 : 0 : call DGETRF(g_mat_size,g_mat_size,inv_g_mat,g_mat_size,ipvt,info)
1514 : 0 : call DGETRI(g_mat_size,inv_g_mat,g_mat_size,ipvt,rework,lwork,info)
1515 : :
1516 : :
1517 : : ! -----------------------------------------------------------
1518 : : ! --Now it calculates the exponential of the matrix h.g
1519 [ # # # # : 0 : hg_mat = matmul(h_mat,g_mat)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1520 : :
1521 : 0 : call exp_mat(hg_mat,g_mat_size,-one/temperature)
1522 : :
1523 : : ! --(exp(h.g)-Identity).(g^-1)
1524 [ # # # # : 0 : hg_mat = hg_mat-identity(:,:)
# # ]
1525 : :
1526 : :
1527 : : ! --results on output
1528 [ # # # # : 0 : nlrec%mat_exp_psp_nl(:g_mat_size,:g_mat_size,1+iangol,ipseudo) = matmul(real(hg_mat,dp),inv_g_mat)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1529 : :
1530 : : ! write(std_out,*) nlrec%mat_exp_psp_nl(:g_mat_size,:g_mat_size,1+iangol,ipseudo)
1531 : :
1532 [ # # ]: 0 : ABI_FREE(g_mat)
1533 [ # # ]: 0 : ABI_FREE(hg_mat)
1534 [ # # ]: 0 : ABI_FREE(h_mat)
1535 [ # # ]: 0 : ABI_FREE(inv_g_mat)
1536 [ # # ]: 0 : ABI_FREE(identity)
1537 : : end if
1538 : :
1539 : : end do !enddo on angular moment
1540 : : end do !enddo on pseudos
1541 : :
1542 : :
1543 [ # # ]: 0 : if(debug)then
1544 [ # # # # ]: 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' pspnl_hgh_rec : exit '
1545 : 0 : call wrtout(std_out,msg,'COLL')
1546 : : end if
1547 : :
1548 [ # # # # : 0 : end subroutine pspnl_hgh_rec
# # # # #
# # # ]
1549 : : !!***
1550 : :
1551 [ # # ]: 0 : end module m_rec
1552 : : !!***
|