Line data Source code
1 : !!****m* ABINIT/m_xg_nonlop
2 : !! NAME
3 : !! m_xg_nonlop
4 : !!
5 : !! FUNCTION
6 : !! This module provides functions to compute the nonlocal operator by means of the BLAS GEMM
7 : !! routine. By treating ndat simultaneous wavefunctions, it is able to exploit BLAS3 routines,
8 : !! which leads to excellent CPU efficiency and OpenMP scalability.
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2022-2026 ABINIT group (LB)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public License, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !!
16 : !! SOURCE
17 :
18 : #if defined HAVE_CONFIG_H
19 : #include "config.h"
20 : #endif
21 :
22 : #include "abi_common.h"
23 :
24 : module m_xg_nonlop
25 :
26 : use defs_basis
27 : use m_errors
28 : use m_abicore
29 : use m_xmpi
30 : ! use m_abi_linalg
31 : use m_xg
32 : use m_xomp
33 : #ifdef HAVE_OPENMP
34 : use omp_lib
35 : #endif
36 :
37 : use m_time, only : timab
38 : use defs_abitypes, only : MPI_type
39 :
40 : use m_paw_ij, only : paw_ij_type
41 : use m_pawtab, only : pawtab_type
42 :
43 : implicit none
44 :
45 : private
46 :
47 : double precision, parameter :: inv_sqrt2 = 1/sqrt2
48 :
49 : ! Independent timers of xg_nonlop :
50 : integer, parameter :: tim_getcprj = 2101
51 : integer, parameter :: tim_apply_prj = 2102
52 : integer, parameter :: tim_apply_Aij = 2103
53 : integer, parameter :: tim_mult_cprj = 2104
54 : integer, parameter :: tim_make_k = 2105
55 : integer, parameter :: tim_make_Dij = 2106
56 : integer, parameter :: tim_make_Sij = 2107
57 : integer, parameter :: tim_make_ekb = 2108
58 : integer, parameter :: tim_apply_diag = 2109
59 : integer, parameter :: tim_init = 2110
60 :
61 : ! Timers that depend on other xg_nonlop timers :
62 : integer, parameter :: tim_getXSY = 2120
63 : integer, parameter :: tim_getXHY = 2121
64 : integer, parameter :: tim_getHmeSX = 2122
65 : integer, parameter :: tim_iter_refinement = 2123
66 :
67 : integer, parameter :: tim_getcprj_gemm = 2130
68 : integer, parameter :: tim_getcprj_copy = 2131
69 : integer, parameter :: tim_getcprj_mpi = 2132
70 : integer, parameter :: tim_getcprj_otf = 2133
71 :
72 : integer, parameter :: tim_apply_prj_gemm = 2135
73 : integer, parameter :: tim_apply_prj_copy = 2136
74 : integer, parameter :: tim_apply_prj_mpi = 2137
75 : integer, parameter :: tim_apply_prj_otf = 2138
76 :
77 : integer, parameter :: tim_mult_cprj_gemm = 2140
78 : integer, parameter :: tim_mult_cprj_copy = 2141
79 : integer, parameter :: tim_mult_cprj_mpi = 2142
80 :
81 : integer, parameter :: tim_forces_stress = 2150
82 : integer, parameter :: tim_fst_start = 2151
83 : integer, parameter :: tim_fst_cprj_deriv_f = 2152
84 : integer, parameter :: tim_fst_cprj_deriv_str = 2153
85 : integer, parameter :: tim_fst_mult_cprj_f = 2154
86 : integer, parameter :: tim_fst_mult_cprj_str = 2155
87 : integer, parameter :: tim_fst_work_str = 2156
88 :
89 : integer, parameter, public :: DERIV_ATOM = 1
90 : integer, parameter, public :: DERIV_STRESS = 2
91 :
92 : type,public :: xg_nonlop_t
93 :
94 : integer :: cplex
95 : integer :: cplex_alldij
96 : integer :: cprjdim
97 : integer :: comm_atom
98 : integer :: comm_band
99 : integer :: npw_k
100 : integer :: total_npw_k
101 : integer :: max_npw_k
102 : integer :: me_band
103 : integer :: my_natom
104 : integer :: natom
105 : integer :: mkmem
106 : integer :: nlmn_max
107 : integer :: ntypat
108 : integer :: nspinor
109 : integer :: space_pw
110 : integer :: space_cprj
111 : integer :: space_Dij
112 : logical :: paw
113 : integer :: option
114 : real(dp) :: weight
115 :
116 : integer, pointer :: mpi_atmtab(:)
117 : integer, pointer :: indlmn(:,:,:)
118 : integer, pointer :: nattyp(:)
119 :
120 : integer,allocatable :: l_npw_k(:)
121 : integer,allocatable :: l_shift_npw_k(:)
122 :
123 : real(dp), pointer :: sij_triangular_mat(:,:)
124 :
125 : integer, allocatable :: nlmn_natom(:)
126 : integer, allocatable :: nlmn_ntypat(:)
127 :
128 : real(dp), pointer :: ffnl_k(:,:,:,:)
129 : real(dp), pointer :: ph3d_k(:,:,:)
130 :
131 : real(dp), pointer :: kpg_k(:,:)
132 :
133 : type(xg_t),pointer :: projectors(:)
134 : type(xg_t),pointer :: projectors_k
135 :
136 : type(xg_t),pointer :: ffnl_gather(:)
137 : type(xg_t),pointer :: ffnl_gather_k
138 :
139 : type(xg_t),pointer :: ph3d_gather(:)
140 : type(xg_t),pointer :: ph3d_gather_k
141 :
142 : ! non paw only:
143 : type(xg_t) :: ekb
144 : ! end non paw only
145 :
146 : ! paw only:
147 : type(xg_t),pointer :: gram_proj(:)
148 : type(xg_t),pointer :: gram_proj_k
149 :
150 : type(xg_t) :: Dij
151 : type(xgBlock_t) :: Dij_spin
152 : type(xg_t) :: Sij
153 :
154 : type(xg_t) :: Sijm1
155 : type(xg_t), pointer :: invSij_approx(:)
156 : type(xg_t), pointer :: invSij_approx_k
157 : ! end paw only
158 :
159 : end type xg_nonlop_t
160 : !!***
161 :
162 : ! To initialize/make/destroy xg_nonlop object
163 : public :: xg_nonlop_init
164 : public :: xg_nonlop_make_k
165 : public :: xg_nonlop_destroy
166 : public :: xg_nonlop_make_ekb ! non paw only
167 : public :: xg_nonlop_destroy_ekb ! non paw only
168 : public :: xg_nonlop_update_weight
169 : public :: xg_nonlop_init_cplex_alldij ! paw only
170 : public :: xg_nonlop_make_Dij ! paw only
171 : public :: xg_nonlop_set_Dij_spin! paw only
172 : public :: xg_nonlop_make_Sij ! paw only
173 : public :: xg_nonlop_destroy_Dij ! paw only
174 : public :: xg_nonlop_destroy_Sij ! paw only
175 : ! Generic operations
176 : public :: xg_nonlop_getcprj
177 : public :: xg_nonlop_apply_Aij
178 : public :: xg_nonlop_precond_iterative_refinement
179 : public :: xg_nonlop_mult_cprj
180 : public :: xg_nonlop_apply_prj
181 : public :: xg_nonlop_colwiseXAX
182 : public :: xg_nonlop_colwiseXDX
183 : public :: xg_nonlop_getXAY
184 : public :: xg_nonlop_getXDY
185 : public :: xg_nonlop_getAX
186 : public :: xg_nonlop_getDX
187 : ! Specific operations (using Sij/Dij or ekb arrays)
188 : public :: xg_nonlop_getXHY
189 : public :: xg_nonlop_getHX
190 : public :: xg_nonlop_colwiseXHX
191 : public :: xg_nonlop_getXSY ! paw only
192 : public :: xg_nonlop_getSX ! paw only
193 : public :: xg_nonlop_getSm1X ! paw only
194 : public :: xg_nonlop_getHmeSX ! paw only
195 : public :: xg_nonlop_forces_stress
196 :
197 : contains
198 : !!***
199 :
200 : !!****f* m_xg_nonlop/xg_nonlop_init
201 : !! NAME
202 : !! xg_nonlop_init
203 : !!
204 : !! FUNCTION
205 : !! Initalization of the xg_nonlop_kpt array
206 : !!
207 : !! INPUTS
208 : !!
209 : !! SOURCE
210 :
211 162 : subroutine xg_nonlop_init(xg_nonlop,indlmn,my_natom,nattyp,mkmem,ntypat,nspinor,ucvol,usepaw,&
212 162 : xg_nonlop_option,me_band,comm_band,comm_atom,mpi_atmtab)
213 :
214 : integer ,intent(in) :: me_band,comm_band,comm_atom
215 : integer ,intent(in) :: my_natom
216 : integer ,intent(in) :: mkmem
217 : integer ,intent(in) :: ntypat
218 : integer ,intent(in) :: nspinor
219 : integer ,intent(in) :: usepaw
220 : integer ,intent(in) :: xg_nonlop_option
221 : real(dp),intent(in) :: ucvol
222 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
223 :
224 : integer,optional,intent(in),target :: mpi_atmtab(:)
225 : integer,intent(in),target :: indlmn(:,:,:)
226 : integer,intent(in),target :: nattyp(:)
227 : real(dp) :: tsec(2)
228 :
229 : integer :: itypat,cprjdim,nlmn,nlmn_max,natom,shift,nmpi,nattyp_i
230 :
231 162 : call timab(tim_init,1,tsec)
232 :
233 162 : xg_nonlop%mkmem=mkmem
234 162 : xg_nonlop%nspinor=nspinor
235 162 : xg_nonlop%comm_atom=comm_atom
236 162 : if (xmpi_comm_size(comm_atom)>1) then
237 108 : if (present(mpi_atmtab)) then
238 108 : xg_nonlop%mpi_atmtab=>mpi_atmtab
239 : else
240 0 : ABI_ERROR("mpi_atmtab must be present")
241 : end if
242 : else
243 54 : xg_nonlop%mpi_atmtab=>null()
244 : end if
245 162 : xg_nonlop%my_natom=my_natom
246 162 : xg_nonlop%me_band=me_band
247 162 : xg_nonlop%comm_band=comm_band
248 :
249 162 : if (xg_nonlop_option==0.or.xg_nonlop_option==1) then
250 162 : xg_nonlop%option = xg_nonlop_option
251 : else
252 0 : ABI_ERROR('Wrong value of xg_nonlop_option')
253 : end if
254 :
255 162 : xg_nonlop%paw=usepaw==1
256 :
257 162 : xg_nonlop%space_pw=0
258 162 : xg_nonlop%space_cprj=0
259 162 : xg_nonlop%space_Dij=0
260 :
261 162 : xg_nonlop%weight=four_pi/sqrt(ucvol)
262 162 : xg_nonlop%ntypat=ntypat
263 :
264 162 : xg_nonlop%nattyp=>nattyp
265 162 : xg_nonlop%indlmn=>indlmn
266 :
267 162 : natom=0
268 476 : do itypat=1,ntypat
269 476 : natom = natom + nattyp(itypat)
270 : end do
271 :
272 486 : ABI_MALLOC(xg_nonlop%nlmn_ntypat,(ntypat))
273 486 : ABI_MALLOC(xg_nonlop%nlmn_natom,(natom))
274 :
275 162 : cprjdim=0
276 162 : shift=0
277 162 : nlmn_max=0
278 476 : do itypat=1,ntypat
279 4842 : nlmn = count(indlmn(3,:,itypat)>0)
280 314 : if (nlmn>nlmn_max) nlmn_max=nlmn
281 314 : xg_nonlop%nlmn_ntypat(itypat) = nlmn
282 314 : nattyp_i = nattyp(itypat)
283 476 : if (nattyp_i>0) then
284 310 : cprjdim = cprjdim + nattyp_i*nlmn
285 674 : xg_nonlop%nlmn_natom(1+shift:nattyp_i+shift) = nlmn
286 : shift = shift + nattyp_i
287 : end if
288 : end do
289 162 : xg_nonlop%nlmn_max = nlmn_max
290 162 : xg_nonlop%natom = natom
291 162 : xg_nonlop%cprjdim = cprjdim
292 :
293 1585 : ABI_MALLOC(xg_nonlop%projectors,(mkmem))
294 1423 : ABI_MALLOC(xg_nonlop%ffnl_gather,(mkmem))
295 1423 : ABI_MALLOC(xg_nonlop%ph3d_gather,(mkmem))
296 162 : if (xg_nonlop%paw) then
297 1183 : ABI_MALLOC(xg_nonlop%gram_proj,(mkmem))
298 1183 : ABI_MALLOC(xg_nonlop%invSij_approx,(mkmem))
299 : end if
300 :
301 162 : nmpi = xmpi_comm_size(xg_nonlop%comm_band)
302 486 : ABI_MALLOC(xg_nonlop%l_npw_k,(nmpi))
303 324 : ABI_MALLOC(xg_nonlop%l_shift_npw_k,(nmpi))
304 :
305 162 : call timab(tim_init,2,tsec)
306 :
307 162 : end subroutine xg_nonlop_init
308 : !!***
309 :
310 : !!****f* m_xg_nonlop/xg_nonlop_update_weight
311 : !! NAME
312 : !! xg_nonlop_init
313 : !!
314 : !! FUNCTION
315 : !! Compute new weights with respect to ucvol
316 : !!
317 : !! INPUTS
318 : !!
319 : !! SOURCE
320 2572 : subroutine xg_nonlop_update_weight(xg_nonlop,ucvol)
321 :
322 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
323 : real(dp),intent(in) :: ucvol
324 :
325 2572 : xg_nonlop%weight=four_pi/sqrt(ucvol)
326 :
327 2572 : end subroutine xg_nonlop_update_weight
328 : !!***
329 :
330 : !!****f* m_xg_nonlop/xg_nonlop_init_cplex_alldij
331 : !! NAME
332 : !! xg_nonlop_init_cplex_alldij
333 : !!
334 : !! FUNCTION
335 : !!
336 : !! INPUTS
337 : !!
338 : !! SOURCE
339 142 : subroutine xg_nonlop_init_cplex_alldij(xg_nonlop,paw_ij)
340 :
341 : type(paw_ij_type),intent(in) :: paw_ij(:)
342 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
343 :
344 : logical :: paral_atom
345 : integer :: iatom,iatom_tot,ierr
346 : integer,allocatable :: l_cplex(:)
347 : real(dp) :: tsec(2)
348 :
349 142 : call timab(tim_init,1,tsec)
350 :
351 142 : paral_atom=(xmpi_comm_size(xg_nonlop%comm_atom)>1)
352 :
353 426 : ABI_MALLOC(l_cplex,(xg_nonlop%natom))
354 466 : l_cplex=0
355 280 : do iatom=1,xg_nonlop%my_natom ! loop over atoms treated by this proc
356 138 : iatom_tot=iatom;if (paral_atom) iatom_tot=xg_nonlop%mpi_atmtab(iatom)
357 280 : l_cplex(iatom_tot)=paw_ij(iatom)%cplex_dij
358 : end do
359 142 : call xmpi_sum(l_cplex,xg_nonlop%comm_atom,ierr)
360 142 : xg_nonlop%cplex_alldij = 0
361 466 : do iatom=1,xg_nonlop%natom ! loop over all atoms
362 466 : if (xg_nonlop%cplex_alldij<l_cplex(iatom)) xg_nonlop%cplex_alldij=l_cplex(iatom)
363 : end do
364 142 : ABI_FREE(l_cplex)
365 :
366 142 : call timab(tim_init,2,tsec)
367 :
368 142 : end subroutine xg_nonlop_init_cplex_alldij
369 : !!***
370 :
371 162 : subroutine xg_nonlop_destroy(xg_nonlop)
372 :
373 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
374 :
375 : integer :: ikpt
376 :
377 162 : if (xg_nonlop%paw) then
378 138 : call xg_nonlop_destroy_Sij(xg_nonlop) ! Can be destroyed before
379 138 : call xg_nonlop_destroy_Dij(xg_nonlop) ! Can be destroyed before
380 : else
381 24 : call xg_nonlop_destroy_ekb(xg_nonlop) ! Can be destroyed before
382 : end if
383 :
384 162 : ABI_FREE(xg_nonlop%nlmn_ntypat)
385 162 : ABI_FREE(xg_nonlop%nlmn_natom)
386 :
387 162 : ABI_FREE(xg_nonlop%l_npw_k)
388 162 : ABI_FREE(xg_nonlop%l_shift_npw_k)
389 :
390 1261 : do ikpt=1,xg_nonlop%mkmem
391 1099 : call xg_free(xg_nonlop%projectors(ikpt))
392 1099 : call xg_free(xg_nonlop%ffnl_gather(ikpt))
393 1099 : call xg_free(xg_nonlop%ph3d_gather(ikpt))
394 1261 : if (xg_nonlop%paw) then
395 907 : call xg_free(xg_nonlop%gram_proj(ikpt))
396 907 : call xg_free(xg_nonlop%invSij_approx(ikpt))
397 : end if
398 : end do
399 162 : ABI_FREE(xg_nonlop%projectors)
400 162 : ABI_FREE(xg_nonlop%ffnl_gather)
401 162 : ABI_FREE(xg_nonlop%ph3d_gather)
402 162 : if (xg_nonlop%paw) then
403 138 : ABI_FREE(xg_nonlop%gram_proj)
404 138 : ABI_FREE(xg_nonlop%invSij_approx)
405 : end if
406 :
407 162 : end subroutine xg_nonlop_destroy
408 : !!***
409 :
410 24 : subroutine xg_nonlop_make_ekb(xg_nonlop,ekb)
411 :
412 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
413 : real(dp), intent(in) :: ekb(:,:)
414 :
415 : integer :: itypat, ilmn, iln, nlmn, nlmn_max, ntypat
416 24 : real(dp),pointer :: ekb_(:)
417 : real(dp) :: tsec(2)
418 : type(xgBlock_t) :: ekb_itypat
419 :
420 : ! *************************************************************************
421 :
422 24 : call timab(tim_make_ekb,1,tsec)
423 :
424 24 : if (xg_nonlop%paw) then
425 0 : ABI_ERROR('Not implemented with paw=True.')
426 : end if
427 :
428 24 : ntypat = xg_nonlop%ntypat
429 24 : nlmn_max = xg_nonlop%nlmn_max
430 :
431 24 : call xg_init(xg_nonlop%ekb,SPACE_R,nlmn_max,ntypat,xmpi_comm_self)
432 :
433 72 : do itypat=1,ntypat
434 :
435 48 : nlmn=xg_nonlop%nlmn_ntypat(itypat)
436 48 : call xg_setBlock(xg_nonlop%ekb,ekb_itypat,nlmn,1,fcol=itypat)
437 48 : call xgBlock_reverseMap_1D(ekb_itypat,ekb_)
438 1584 : do ilmn=1,nlmn
439 1512 : iln=xg_nonlop%indlmn(5,ilmn,itypat)
440 1560 : ekb_(ilmn) = ekb(iln,itypat)
441 : end do
442 :
443 : end do
444 :
445 24 : call timab(tim_make_ekb,2,tsec)
446 :
447 24 : end subroutine xg_nonlop_make_ekb
448 : !!***
449 :
450 2188 : subroutine xg_nonlop_make_Dij(xg_nonlop,paw_ij,nsppol,atindx)
451 :
452 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
453 : type(paw_ij_type),intent(in) :: paw_ij(:)
454 : integer,intent(in) :: nsppol
455 : integer,intent(in) :: atindx(:)
456 :
457 : logical :: paral_atom
458 : integer :: isppol, iatom, iatom_input, iatom_type, nlmn, nlmn_max, natom, nspinor, shift
459 : integer :: ilmn, jlmn, j0lmn, jjlmn, ijlmn
460 : integer :: cplex_alldij,cplex_dij,isp,isps,jsp,jsps,ijsp
461 2188 : real(dp),pointer :: Dij_iatom_(:,:)
462 : real(dp) :: tsec(2)
463 : type(xgBlock_t) :: Dij_iatom
464 :
465 : ! *************************************************************************
466 :
467 2188 : call timab(tim_make_Dij,1,tsec)
468 :
469 2188 : if (.not.xg_nonlop%paw) then
470 0 : ABI_ERROR('Not implemented with paw=False.')
471 : end if
472 :
473 2188 : nspinor = xg_nonlop%nspinor
474 2188 : natom = xg_nonlop%natom
475 2188 : nlmn_max = xg_nonlop%nlmn_max
476 :
477 2188 : paral_atom=(xmpi_comm_size(xg_nonlop%comm_atom)>1)
478 :
479 2188 : cplex_alldij = xg_nonlop%cplex_alldij
480 2188 : if (cplex_alldij==1) then
481 1645 : xg_nonlop%space_Dij=SPACE_R
482 543 : else if (cplex_alldij==2) then
483 543 : xg_nonlop%space_Dij=SPACE_C
484 : else
485 0 : ABI_ERROR('Bad cplex_alldij')
486 : end if
487 :
488 2188 : call xg_init(xg_nonlop%Dij,xg_nonlop%space_Dij,nspinor*nlmn_max,nspinor*nlmn_max*natom*nsppol,xmpi_comm_null)
489 :
490 4440 : do isppol=1,nsppol
491 :
492 6518 : do iatom=1,xg_nonlop%my_natom ! loop over atoms treated by this proc
493 2078 : iatom_input = iatom
494 2078 : if (paral_atom) iatom_input=xg_nonlop%mpi_atmtab(iatom) ! mpi_atmtab(iatom) has the ordering of the input file
495 2078 : iatom_type = atindx(iatom_input) ! convert iatom from input file to iatom ordered by type
496 2078 : nlmn=xg_nonlop%nlmn_natom(iatom_type)
497 2078 : shift=1+(iatom_type-1)*nspinor*nlmn_max+(isppol-1)*natom*nspinor*nlmn_max
498 2078 : call xg_setBlock(xg_nonlop%Dij,Dij_iatom,nspinor*nlmn,nspinor*nlmn,fcol=shift)
499 2078 : cplex_dij=paw_ij(iatom)%cplex_dij
500 2078 : call xgBlock_reverseMap(Dij_iatom,Dij_iatom_)
501 6822 : do jsp=1,nspinor
502 2492 : jsps = (jsp-1)*nlmn
503 27246 : do jlmn=1,nlmn
504 22676 : j0lmn=jlmn*(jlmn-1)/2
505 22676 : jjlmn=j0lmn+jlmn
506 55708 : do isp=1,nspinor
507 30540 : isps = (isp-1)*nlmn
508 30540 : if (nspinor==1) then
509 : ijsp = isppol
510 : else
511 15728 : if (isp==jsp) then
512 : ijsp = isp
513 7864 : else if (isp==1) then
514 : ijsp = 3 ! up/down
515 : else
516 3932 : ijsp = 4 ! down/up
517 : end if
518 : end if
519 : ! see m_hamiltonian:pawdij2ekb
520 30540 : if (cplex_dij==1) then
521 14812 : Dij_iatom_(cplex_alldij*(jlmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(jjlmn,ijsp)
522 14812 : if (cplex_alldij==2) Dij_iatom_(2*(jlmn+isps),jlmn+jsps) = zero
523 : else
524 15728 : Dij_iatom_(2*(jlmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(2*jjlmn-1,ijsp)
525 15728 : Dij_iatom_(2*(jlmn+isps) ,jlmn+jsps) = paw_ij(iatom)%dij(2*jjlmn ,ijsp)
526 : end if
527 195926 : do ilmn=1,jlmn-1
528 : ! see m_hamiltonian:pawdij2ekb and opernlc_ylm
529 142710 : ijlmn=j0lmn+ilmn
530 173250 : if (cplex_dij==1) then
531 65342 : Dij_iatom_(cplex_alldij*(ilmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(ijlmn,ijsp)
532 65342 : if (cplex_alldij==2) Dij_iatom_(2*(ilmn+isps),jlmn+jsps) = zero
533 65342 : Dij_iatom_(cplex_alldij*(jlmn+jsps-1)+1,ilmn+isps) = paw_ij(iatom)%dij(ijlmn,ijsp)
534 65342 : if (cplex_alldij==2) Dij_iatom_(2*(jlmn+jsps),ilmn+isps) = zero
535 : else
536 77368 : Dij_iatom_(2*(ilmn+isps-1)+1,jlmn+jsps) = paw_ij(iatom)%dij(2*ijlmn-1,ijsp)
537 77368 : Dij_iatom_(2*(ilmn+isps) ,jlmn+jsps) = paw_ij(iatom)%dij(2*ijlmn ,ijsp)
538 77368 : Dij_iatom_(2*(jlmn+jsps-1)+1,ilmn+isps) = paw_ij(iatom)%dij(2*ijlmn-1,ijsp)
539 77368 : Dij_iatom_(2*(jlmn+jsps) ,ilmn+isps) =-paw_ij(iatom)%dij(2*ijlmn ,ijsp)
540 : end if
541 : end do
542 : end do
543 : end do
544 : end do
545 : end do
546 :
547 : end do
548 :
549 : ! Communication in case of distribution over atomic sites
550 2188 : if (paral_atom) then
551 1692 : call xgBlock_mpi_sum(xg_nonlop%Dij%self,comm=xg_nonlop%comm_atom)
552 : end if
553 :
554 2188 : call timab(tim_make_Dij,2,tsec)
555 :
556 2188 : end subroutine xg_nonlop_make_Dij
557 : !!***
558 :
559 2252 : subroutine xg_nonlop_set_Dij_spin(xg_nonlop,isppol)
560 :
561 : integer,intent(in) :: isppol
562 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
563 :
564 : integer :: shift,nlmn_max,nspinor,natom
565 :
566 2252 : nspinor = xg_nonlop%nspinor
567 2252 : natom = xg_nonlop%natom
568 2252 : nlmn_max = xg_nonlop%nlmn_max
569 :
570 2252 : if (isppol/=1) then ! isppol must be 1 or 2 if nspinor==1, and must be 1 of nspinor==2
571 64 : if (isppol/=2.or.nspinor/=1) then
572 0 : ABI_ERROR('wrong isppol')
573 : end if
574 : end if
575 :
576 2252 : shift=1+(isppol-1)*natom*nspinor*nlmn_max
577 2252 : call xg_setBlock(xg_nonlop%Dij,xg_nonlop%Dij_spin,nspinor*nlmn_max,nspinor*nlmn_max*natom,fcol=shift)
578 :
579 2252 : end subroutine xg_nonlop_set_Dij_spin
580 : !!***
581 :
582 138 : subroutine xg_nonlop_make_Sij(xg_nonlop,pawtab,inv_sij)
583 :
584 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
585 : type(pawtab_type),intent(in) :: pawtab(:)
586 : logical,optional,intent(in) :: inv_sij
587 :
588 : logical :: inv_sij_
589 : integer :: itypat, nlmn, nlmn_max, ntypat, shift
590 : integer :: ilmn, jlmn, j0lmn, jjlmn, ijlmn
591 138 : real(dp),pointer :: Sij_itypat_(:,:)
592 : real(dp) :: tsec(2)
593 : type(xg_t) :: work
594 : type(xgBlock_t) :: Sij_itypat,Sijm1_itypat
595 :
596 : ! *************************************************************************
597 :
598 138 : call timab(tim_make_Sij,1,tsec)
599 :
600 138 : if (.not.xg_nonlop%paw) then
601 0 : ABI_ERROR('Not implemented with paw=False.')
602 : end if
603 :
604 138 : ntypat = xg_nonlop%ntypat
605 138 : nlmn_max = xg_nonlop%nlmn_max
606 :
607 138 : call xg_init(xg_nonlop%Sij,SPACE_R,nlmn_max,nlmn_max*ntypat,xmpi_comm_self)
608 :
609 138 : inv_sij_ = .false.
610 138 : if (present(inv_sij)) inv_sij_ = inv_sij
611 :
612 138 : if (inv_sij_) then
613 102 : call xg_init(xg_nonlop%Sijm1,SPACE_R,nlmn_max,nlmn_max*ntypat,xmpi_comm_self)
614 : end if
615 :
616 404 : do itypat=1,ntypat
617 :
618 266 : nlmn=xg_nonlop%nlmn_ntypat(itypat)
619 :
620 266 : shift=1+(itypat-1)*nlmn_max
621 266 : call xg_setBlock(xg_nonlop%Sij,Sij_itypat,nlmn,nlmn,fcol=shift)
622 266 : call xgBlock_reverseMap(Sij_itypat,Sij_itypat_)
623 2584 : do jlmn=1,nlmn
624 2318 : j0lmn=jlmn*(jlmn-1)/2
625 2318 : jjlmn=j0lmn+jlmn
626 2318 : Sij_itypat_(jlmn,jlmn) = pawtab(itypat)%sij(jjlmn)
627 12407 : do ilmn=1,jlmn-1
628 9823 : ijlmn=j0lmn+ilmn
629 9823 : Sij_itypat_(ilmn,jlmn) = pawtab(itypat)%sij(ijlmn)
630 12141 : Sij_itypat_(jlmn,ilmn) = pawtab(itypat)%sij(ijlmn)
631 : end do
632 : end do
633 404 : if (inv_sij_) then
634 207 : call xg_init(work,SPACE_R,nlmn,nlmn,xmpi_comm_self)
635 207 : call xg_setBlock(xg_nonlop%Sijm1,Sijm1_itypat,nlmn,nlmn,fcol=shift)
636 207 : call xgBlock_invert_sy(Sijm1_itypat,work%self,xg_input=Sij_itypat)
637 207 : call xg_free(work)
638 : end if
639 :
640 : end do
641 :
642 138 : call timab(tim_make_Sij,2,tsec)
643 :
644 138 : end subroutine xg_nonlop_make_Sij
645 : !!***
646 :
647 24 : subroutine xg_nonlop_destroy_ekb(xg_nonlop)
648 :
649 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
650 :
651 : ! *************************************************************************
652 :
653 24 : if (xg_nonlop%paw) then
654 0 : ABI_ERROR('Not implemented with paw=True.')
655 : end if
656 :
657 24 : call xg_free(xg_nonlop%ekb)
658 :
659 24 : end subroutine xg_nonlop_destroy_ekb
660 : !!***
661 :
662 2326 : subroutine xg_nonlop_destroy_Dij(xg_nonlop)
663 :
664 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
665 :
666 : ! *************************************************************************
667 :
668 2326 : if (.not.xg_nonlop%paw) then
669 0 : ABI_ERROR('Not implemented with paw=False.')
670 : end if
671 :
672 2326 : call xg_free(xg_nonlop%Dij)
673 :
674 2326 : end subroutine xg_nonlop_destroy_Dij
675 : !!***
676 :
677 138 : subroutine xg_nonlop_destroy_Sij(xg_nonlop)
678 :
679 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
680 :
681 : ! *************************************************************************
682 :
683 138 : if (.not.xg_nonlop%paw) then
684 0 : ABI_ERROR('Not implemented with paw=False.')
685 : end if
686 :
687 138 : call xg_free(xg_nonlop%Sij)
688 138 : call xg_free(xg_nonlop%Sijm1)
689 :
690 138 : end subroutine xg_nonlop_destroy_Sij
691 : !!***
692 :
693 2320 : subroutine xg_nonlop_compute_projs(xg_nonlop)
694 :
695 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
696 :
697 2320 : complex(dp),pointer :: projectors_k_(:,:)
698 2320 : real(dp),pointer :: projectors_k_real(:,:)
699 2320 : real(dp),pointer :: ffnl_gather_k_(:,:)
700 2320 : complex(dp),pointer :: ph3d_gather_k_(:,:)
701 2320 : real(dp),pointer :: ph3d_gather_k_real(:,:)
702 :
703 : integer :: shift_itypat,shift_itypat_nlmn,ntypat,nattyp_i,shift_ipw
704 : integer :: icol,ilmn,nlmn,il,ipw,ia,iatom,itypat
705 : real(dp) :: ffnl_ipw
706 : complex(dp) :: cil(4),ph3d_ipw,ctmp
707 : logical :: compute_gather
708 :
709 2320 : ntypat = xg_nonlop%ntypat
710 :
711 : ! 4pi/sqrt(ucvol) * (-i)^l
712 2320 : cil(1) = ( 1.0_DP, 0.0_DP) * xg_nonlop%weight
713 2320 : cil(2) = ( 0.0_DP,-1.0_DP) * xg_nonlop%weight
714 2320 : cil(3) = (-1.0_DP, 0.0_DP) * xg_nonlop%weight
715 2320 : cil(4) = ( 0.0_DP, 1.0_DP) * xg_nonlop%weight
716 :
717 2320 : compute_gather = xg_nonlop%option==0
718 :
719 2320 : if (compute_gather) then
720 2192 : call xgBlock_zero(xg_nonlop%ffnl_gather_k%self)
721 2192 : call xgBlock_zero(xg_nonlop%ph3d_gather_k%self)
722 2192 : call xgBlock_reverseMap(xg_nonlop%ffnl_gather_k%self,ffnl_gather_k_)
723 : end if
724 :
725 2320 : shift_ipw = xg_nonlop%l_shift_npw_k(xg_nonlop%me_band+1)
726 :
727 3654 : select case(xg_nonlop%space_pw)
728 :
729 : case (SPACE_C)
730 :
731 1334 : call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_)
732 1334 : if (compute_gather) then
733 1206 : call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_)
734 : end if
735 : shift_itypat=0
736 : shift_itypat_nlmn=0
737 : !$omp parallel default (none) &
738 : !$omp& shared(xg_nonlop,ph3d_gather_k_,ffnl_gather_k_,projectors_k_), &
739 : !$omp& firstprivate(compute_gather,ntypat,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
740 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw,ffnl_ipw,icol)
741 4048 : do itypat = 1, ntypat
742 2714 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
743 2714 : nattyp_i = xg_nonlop%nattyp(itypat)
744 4048 : if (nattyp_i>0) then
745 : !! projectors = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * ffnl
746 : !$omp do collapse(3)
747 5350 : do ia = 1, nattyp_i
748 30478 : do ilmn=1,nlmn
749 2192660 : do ipw=1,xg_nonlop%npw_k
750 2164832 : iatom = ia + shift_itypat
751 2164832 : il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
752 2164832 : ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
753 2164832 : ffnl_ipw = xg_nonlop%ffnl_k(ipw, 1, ilmn, itypat)
754 : !
755 2164832 : if (compute_gather) then
756 2096544 : ph3d_gather_k_(ipw+shift_ipw,iatom) = ph3d_ipw
757 2096544 : ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max) = ffnl_ipw
758 : end if
759 : !
760 2164832 : icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
761 2189960 : projectors_k_(ipw,icol) = cil(il) * conjg(ph3d_ipw) * ffnl_ipw
762 : end do
763 : end do
764 : end do
765 : !$omp end do
766 2650 : shift_itypat = shift_itypat + nattyp_i
767 2650 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
768 : end if
769 : end do
770 : !$omp end parallel
771 :
772 : case (SPACE_CR)
773 :
774 986 : call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_real)
775 986 : if (compute_gather) then
776 986 : call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_real)
777 : end if
778 : shift_itypat=0
779 : shift_itypat_nlmn=0
780 : !$omp parallel default (none) &
781 : !$omp& shared(xg_nonlop,ph3d_gather_k_real,ffnl_gather_k_,projectors_k_real), &
782 : !$omp& firstprivate(compute_gather,ntypat,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
783 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw,ffnl_ipw,icol,ctmp)
784 2948 : do itypat = 1, ntypat
785 1962 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
786 1962 : nattyp_i = xg_nonlop%nattyp(itypat)
787 2948 : if (nattyp_i>0) then
788 : !! projectors = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * ffnl
789 : !$omp do collapse(3)
790 3934 : do ia = 1, nattyp_i
791 34950 : do ilmn=1,nlmn
792 952300 : do ipw=1,xg_nonlop%npw_k
793 919312 : iatom = ia + shift_itypat
794 919312 : il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
795 919312 : ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
796 919312 : ffnl_ipw = xg_nonlop%ffnl_k(ipw, 1, ilmn, itypat)
797 : !
798 919312 : if (compute_gather) then
799 919312 : ph3d_gather_k_real(2*(ipw+shift_ipw)-1,iatom) = dble(ph3d_ipw)
800 919312 : ph3d_gather_k_real(2*(ipw+shift_ipw) ,iatom) = dimag(ph3d_ipw)
801 919312 : ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max) = ffnl_ipw
802 : end if
803 : !
804 919312 : ctmp = cil(il) * conjg(ph3d_ipw) * ffnl_ipw
805 919312 : icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
806 919312 : projectors_k_real(2*ipw-1,icol) = dble(ctmp)
807 950328 : projectors_k_real(2*ipw ,icol) = dimag(ctmp)
808 : end do
809 : end do
810 : end do
811 : !$omp end do
812 1962 : shift_itypat = shift_itypat + nattyp_i
813 1962 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
814 : end if
815 : end do
816 : !$omp end parallel
817 :
818 : case default
819 2320 : ABI_ERROR("Wrong space")
820 :
821 : end select
822 :
823 2320 : if (compute_gather) then
824 2192 : call xgBlock_mpi_sum(xg_nonlop%ffnl_gather_k%self,comm=xg_nonlop%comm_band)
825 2192 : call xgBlock_mpi_sum(xg_nonlop%ph3d_gather_k%self,comm=xg_nonlop%comm_band)
826 : end if
827 :
828 2320 : end subroutine xg_nonlop_compute_projs
829 : !!***
830 :
831 18300 : subroutine xg_nonlop_compute_projs_deriv_atom(xg_nonlop,projs_deriv_atom)
832 :
833 : type(xgBlock_t),intent(inout) :: projs_deriv_atom
834 : type(xg_nonlop_t),intent(in) :: xg_nonlop
835 :
836 18300 : complex(dp),pointer :: projectors_k_(:,:)
837 18300 : complex(dp),pointer :: projectors_deriv_atom_k_(:,:)
838 18300 : real(dp),pointer :: projectors_k_real(:,:)
839 18300 : real(dp),pointer :: projectors_deriv_atom_k_real(:,:)
840 :
841 : integer :: shift_itypat_nlmn,shift_itypat_3nlmn,ntypat,nattyp_i
842 : integer :: icol,icol_deriv,ilmn,nlmn,ipw,ia,itypat,idir
843 : complex(dp) :: ctmp
844 : real(dp) :: tmp,proj_deriv_ipw_re,proj_deriv_ipw_im
845 :
846 18300 : if (.not.associated(xg_nonlop%projectors_k)) then
847 0 : ABI_ERROR('projectors_k should be associated')
848 : end if
849 :
850 18300 : if (rows(projs_deriv_atom)/=xg_nonlop%npw_k) then
851 0 : ABI_ERROR('rows(projs_deriv_atom)/=npw_k')
852 : end if
853 18300 : if (cols(projs_deriv_atom)/=3*xg_nonlop%cprjdim) then
854 0 : ABI_ERROR('cols(projs_deriv_atom)/=3*cprjdim')
855 : end if
856 :
857 18300 : ntypat = xg_nonlop%ntypat
858 :
859 28903 : select case(xg_nonlop%space_pw)
860 :
861 : case (SPACE_C)
862 :
863 10603 : call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_)
864 10603 : call xgBlock_reverseMap(projs_deriv_atom,projectors_deriv_atom_k_)
865 10603 : shift_itypat_nlmn=0
866 10603 : shift_itypat_3nlmn=0
867 : !$omp parallel default (none) &
868 : !$omp& shared(xg_nonlop,projectors_k_,projectors_deriv_atom_k_), &
869 : !$omp& firstprivate(ntypat,shift_itypat_nlmn,shift_itypat_3nlmn), &
870 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol,icol_deriv,ctmp)
871 32376 : do itypat = 1, ntypat
872 21773 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
873 21773 : nattyp_i = xg_nonlop%nattyp(itypat)
874 32376 : if (nattyp_i>0) then
875 : !! projectors_deriv_atom(k+G) = -i * 2pi * (k+G)_idir * projectors(k+G)
876 : !$omp do collapse(4)
877 42379 : do ia = 1, nattyp_i
878 230887 : do ilmn=1,nlmn
879 16228673 : do ipw=1,xg_nonlop%npw_k
880 64264280 : do idir=1,3
881 48056829 : icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
882 48056829 : ctmp = ( 0.0_DP, -1.0_DP) * two_pi * xg_nonlop%kpg_k(ipw,idir)
883 48056829 : icol_deriv = ilmn + (idir-1)*nlmn + (ia-1)*3*nlmn + shift_itypat_3nlmn
884 64075772 : projectors_deriv_atom_k_(ipw,icol_deriv) = ctmp * projectors_k_(ipw,icol)
885 : end do
886 : end do
887 : end do
888 : end do
889 : !$omp end do
890 21157 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
891 21157 : shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
892 : end if
893 : end do
894 : !$omp end parallel
895 :
896 : case (SPACE_CR)
897 :
898 7697 : call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_real)
899 7697 : call xgBlock_reverseMap(projs_deriv_atom,projectors_deriv_atom_k_real)
900 7697 : shift_itypat_nlmn=0
901 7697 : shift_itypat_3nlmn=0
902 : !$omp parallel default (none) &
903 : !$omp& shared(xg_nonlop,projectors_k_real,projectors_deriv_atom_k_real), &
904 : !$omp& firstprivate(ntypat,shift_itypat_nlmn,shift_itypat_3nlmn), &
905 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol,icol_deriv,tmp), &
906 : !$omp& private(proj_deriv_ipw_re,proj_deriv_ipw_im)
907 23074 : do itypat = 1, ntypat
908 15377 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
909 15377 : nattyp_i = xg_nonlop%nattyp(itypat)
910 23074 : if (nattyp_i>0) then
911 : !! projectors_deriv_atom(k+G) = -i * 2pi * (k+G)_idir * projectors(k+G)
912 : !$omp do collapse(4)
913 30771 : do ia = 1, nattyp_i
914 220063 : do ilmn=1,nlmn
915 6104064 : do ipw=1,xg_nonlop%npw_k
916 23786804 : do idir=1,3
917 17698134 : icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
918 17698134 : tmp = - two_pi * xg_nonlop%kpg_k(ipw,idir)
919 17698134 : icol_deriv = ilmn + (idir-1)*nlmn + (ia-1)*3*nlmn + shift_itypat_3nlmn
920 : !! Re(projectors_deriv_atom) = 2pi * (k+G)_idir * Im(projectors)
921 : !! Im(projectors_deriv_atom) = -2pi * (k+G)_idir * Re(projectors)
922 17698134 : proj_deriv_ipw_re = - tmp * projectors_k_real(2*ipw ,icol)
923 17698134 : proj_deriv_ipw_im = tmp * projectors_k_real(2*ipw-1,icol)
924 17698134 : projectors_deriv_atom_k_real(2*ipw-1,icol_deriv) = proj_deriv_ipw_re
925 23597512 : projectors_deriv_atom_k_real(2*ipw ,icol_deriv) = proj_deriv_ipw_im
926 : end do
927 : end do
928 : end do
929 : end do
930 : !$omp end do
931 15377 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
932 15377 : shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
933 : end if
934 : end do
935 : !$omp end parallel
936 :
937 : case default
938 18300 : ABI_ERROR("Wrong space")
939 :
940 : end select
941 :
942 18300 : end subroutine xg_nonlop_compute_projs_deriv_atom
943 : !!***
944 :
945 1140 : subroutine xg_nonlop_compute_projs_deriv_stress(xg_nonlop,projs_deriv_stress)
946 :
947 : type(xgBlock_t),intent(inout) :: projs_deriv_stress
948 : type(xg_nonlop_t),intent(in) :: xg_nonlop
949 :
950 1140 : complex(dp),pointer :: projectors_k_(:,:)
951 1140 : complex(dp),pointer :: projectors_deriv_stress_k_(:,:)
952 1140 : real(dp),pointer :: projectors_k_real(:,:)
953 1140 : real(dp),pointer :: projectors_deriv_stress_k_real(:,:)
954 :
955 : integer :: shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn,ntypat,nattyp_i
956 : integer :: iatom,icol_shift,icol_deriv,ilmn,nlmn,ipw,ia,itypat,idir,il
957 : complex(dp) :: ctmp(3),cil(4),ph3d_ipw,cipw
958 : real(dp) :: ffnl_ipw(3)
959 :
960 1140 : if (rows(projs_deriv_stress)/=xg_nonlop%npw_k) then
961 0 : ABI_ERROR('rows(projs_deriv_atom)/=npw_k')
962 : end if
963 1140 : if (cols(projs_deriv_stress)/=6*xg_nonlop%cprjdim) then
964 0 : ABI_ERROR('cols(projs_deriv_stress)/=6*cprjdim')
965 : end if
966 :
967 1140 : ntypat = xg_nonlop%ntypat
968 :
969 : ! 4pi/sqrt(ucvol) * (-i)^l
970 1140 : cil(1) = ( 1.0_DP, 0.0_DP) * xg_nonlop%weight
971 1140 : cil(2) = ( 0.0_DP,-1.0_DP) * xg_nonlop%weight
972 1140 : cil(3) = (-1.0_DP, 0.0_DP) * xg_nonlop%weight
973 1140 : cil(4) = ( 0.0_DP, 1.0_DP) * xg_nonlop%weight
974 :
975 1871 : select case(xg_nonlop%space_pw)
976 :
977 : case (SPACE_C)
978 :
979 731 : call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_)
980 731 : call xgBlock_reverseMap(projs_deriv_stress,projectors_deriv_stress_k_)
981 731 : shift_itypat=0
982 731 : shift_itypat_nlmn=0
983 731 : shift_itypat_6nlmn=0
984 : !$omp parallel default (none) &
985 : !$omp& shared(xg_nonlop,projectors_k_,projectors_deriv_stress_k_), &
986 : !$omp& firstprivate(cil,ntypat,shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn), &
987 : !$omp& private(il,iatom,itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol_shift,icol_deriv), &
988 : !$omp& private(ctmp,ph3d_ipw,ffnl_ipw)
989 2176 : do itypat = 1, ntypat
990 1445 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
991 1445 : nattyp_i = xg_nonlop%nattyp(itypat)
992 2176 : if (nattyp_i>0) then
993 : !! projectors_deriv_stress(k+G)_ab = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * (-(k+G)_b) * d/d(K_a)[ffnl_deriv(k+G)]
994 : !$omp do collapse(3)
995 2891 : do ia = 1, nattyp_i
996 17279 : do ilmn=1,nlmn
997 1381698 : do ipw=1,xg_nonlop%npw_k
998 1365832 : iatom = ia + shift_itypat
999 1365832 : il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
1000 1365832 : ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
1001 5463328 : ffnl_ipw(:) = xg_nonlop%ffnl_k(ipw, 2:4, ilmn, itypat)
1002 5463328 : ctmp(:) = - cil(il) * conjg(ph3d_ipw) * xg_nonlop%kpg_k(ipw,:)
1003 1365832 : icol_shift = ilmn + (ia-1)*6*nlmn + shift_itypat_6nlmn
1004 : ! diagonal part
1005 5463328 : do idir=1,3
1006 4097496 : icol_deriv = icol_shift + (idir-1)*nlmn
1007 5463328 : projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(idir) * ffnl_ipw(idir)
1008 : end do
1009 : ! off-diagonal part (which is symmetric)
1010 5463328 : ctmp(:) = half*ctmp(:)
1011 1365832 : icol_deriv = icol_shift + (4-1)*nlmn
1012 1365832 : projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(2) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(2)
1013 1365832 : icol_deriv = icol_shift + (5-1)*nlmn
1014 1365832 : projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(1) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(1)
1015 1365832 : icol_deriv = icol_shift + (6-1)*nlmn
1016 1380220 : projectors_deriv_stress_k_(ipw,icol_deriv) = ctmp(1) * ffnl_ipw(2) + ctmp(2) * ffnl_ipw(1)
1017 : end do
1018 : end do
1019 : end do
1020 : !$omp end do
1021 1413 : shift_itypat = shift_itypat + nattyp_i
1022 1413 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
1023 1413 : shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
1024 : end if
1025 : end do
1026 : !$omp end parallel
1027 :
1028 : case (SPACE_CR)
1029 :
1030 409 : call xgBlock_reverseMap(xg_nonlop%projectors_k%self,projectors_k_real)
1031 409 : call xgBlock_reverseMap(projs_deriv_stress,projectors_deriv_stress_k_real)
1032 409 : shift_itypat=0
1033 409 : shift_itypat_nlmn=0
1034 409 : shift_itypat_6nlmn=0
1035 : !$omp parallel default (none) &
1036 : !$omp& shared(xg_nonlop,projectors_k_real,projectors_deriv_stress_k_real), &
1037 : !$omp& firstprivate(cil,ntypat,shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn), &
1038 : !$omp& private(il,iatom,itypat,nattyp_i,nlmn,ia,ilmn,ipw,idir,icol_shift,icol_deriv), &
1039 : !$omp& private(ctmp,cipw,ph3d_ipw,ffnl_ipw)
1040 1210 : do itypat = 1, ntypat
1041 801 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
1042 801 : nattyp_i = xg_nonlop%nattyp(itypat)
1043 1210 : if (nattyp_i>0) then
1044 : !! projectors_deriv_stress(k+G)_ab = 4pi/sqrt(ucvol) * (-i)^l * conj(ph3d) * (-(k+G)_b) * d/d(K_a)[ffnl_deriv(k+G)]
1045 : !$omp do collapse(3)
1046 1619 : do ia = 1, nattyp_i
1047 14519 : do ilmn=1,nlmn
1048 454776 : do ipw=1,xg_nonlop%npw_k
1049 441058 : iatom = ia + shift_itypat
1050 441058 : il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
1051 441058 : ph3d_ipw = cmplx( xg_nonlop%ph3d_k(1,ipw,iatom), xg_nonlop%ph3d_k(2,ipw,iatom), kind=DP)
1052 1764232 : ffnl_ipw(:) = xg_nonlop%ffnl_k(ipw, 2:4, ilmn, itypat)
1053 1764232 : ctmp(:) = - cil(il) * conjg(ph3d_ipw) * xg_nonlop%kpg_k(ipw,:)
1054 441058 : icol_shift = ilmn + (ia-1)*6*nlmn + shift_itypat_6nlmn
1055 : ! diagonal part
1056 1764232 : do idir=1,3
1057 1323174 : icol_deriv = icol_shift + (idir-1)*nlmn
1058 1323174 : projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) = dble(ctmp(idir)) * ffnl_ipw(idir)
1059 1764232 : projectors_deriv_stress_k_real(2*ipw ,icol_deriv) = dimag(ctmp(idir)) * ffnl_ipw(idir)
1060 : end do
1061 : ! off-diagonal part (which is symmetric)
1062 1764232 : ctmp(:) = half*ctmp(:)
1063 :
1064 441058 : icol_deriv = icol_shift + (4-1)*nlmn
1065 441058 : cipw = ctmp(2) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(2)
1066 441058 : projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) = dble(cipw)
1067 441058 : projectors_deriv_stress_k_real(2*ipw ,icol_deriv) = dimag(cipw)
1068 :
1069 441058 : icol_deriv = icol_shift + (5-1)*nlmn
1070 441058 : cipw = ctmp(1) * ffnl_ipw(3) + ctmp(3) * ffnl_ipw(1)
1071 441058 : projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) = dble(cipw)
1072 441058 : projectors_deriv_stress_k_real(2*ipw ,icol_deriv) = dimag(cipw)
1073 :
1074 441058 : icol_deriv = icol_shift + (6-1)*nlmn
1075 441058 : cipw = ctmp(1) * ffnl_ipw(2) + ctmp(2) * ffnl_ipw(1)
1076 441058 : projectors_deriv_stress_k_real(2*ipw-1,icol_deriv) = dble(cipw)
1077 453958 : projectors_deriv_stress_k_real(2*ipw ,icol_deriv) = dimag(cipw)
1078 :
1079 : end do
1080 : end do
1081 : end do
1082 : !$omp end do
1083 801 : shift_itypat = shift_itypat + nattyp_i
1084 801 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
1085 801 : shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
1086 : end if
1087 : end do
1088 : !$omp end parallel
1089 :
1090 : case default
1091 1140 : ABI_ERROR("Wrong space")
1092 :
1093 : end select
1094 :
1095 1140 : end subroutine xg_nonlop_compute_projs_deriv_stress
1096 : !!***
1097 :
1098 865236 : subroutine xg_nonlop_compute_projs_otf(xg_nonlop,projs_otf,index_mpi)
1099 :
1100 : integer,intent(in) :: index_mpi
1101 : type(xg_nonlop_t),intent(in) :: xg_nonlop
1102 : type(xgBlock_t),intent(inout) :: projs_otf
1103 :
1104 865236 : complex(dp),pointer :: projectors_k_(:,:)
1105 865236 : real(dp),pointer :: projectors_k_real(:,:)
1106 865236 : real(dp),pointer :: ffnl_gather_k_(:,:)
1107 865236 : complex(dp),pointer :: ph3d_gather_k_(:,:)
1108 865236 : real(dp),pointer :: ph3d_gather_k_real(:,:)
1109 :
1110 : integer :: nmpi,npw_k
1111 : integer :: shift_itypat,shift_itypat_nlmn,ntypat,nattyp_i,shift_ipw
1112 : integer :: icol,ilmn,nlmn,il,ipw,ia,iatom,itypat
1113 : real(dp) :: ffnl_ipw,ph3d_ipw_r(2)
1114 : complex(dp) :: cil(4),ph3d_ipw,ctmp
1115 :
1116 865236 : if (xg_nonlop%option/=0) then
1117 0 : ABI_ERROR('xg_nonlop%option/=0')
1118 : end if
1119 :
1120 865236 : nmpi = xmpi_comm_size(xg_nonlop%comm_band)
1121 865236 : if (index_mpi<0.or.index_mpi>nmpi-1) then
1122 0 : ABI_ERROR('index_mpi should be between 0 and size(comm_band)-1')
1123 : end if
1124 :
1125 865236 : npw_k = xg_nonlop%l_npw_k(index_mpi+1)
1126 865236 : shift_ipw = xg_nonlop%l_shift_npw_k(index_mpi+1)
1127 :
1128 865236 : if (rows(projs_otf)/=npw_k) then
1129 0 : ABI_ERROR('rows(projs_otf)/=npw_k!')
1130 : end if
1131 865236 : if (cols(projs_otf)/=xg_nonlop%cprjdim) then
1132 0 : ABI_ERROR('cols(projs_otf)/=cprjdim!')
1133 : end if
1134 :
1135 865236 : ntypat = xg_nonlop%ntypat
1136 :
1137 : ! 4pi/sqrt(ucvol) * (-i)^l
1138 865236 : cil(1) = ( 1.0_DP, 0.0_DP) * xg_nonlop%weight
1139 865236 : cil(2) = ( 0.0_DP,-1.0_DP) * xg_nonlop%weight
1140 865236 : cil(3) = (-1.0_DP, 0.0_DP) * xg_nonlop%weight
1141 865236 : cil(4) = ( 0.0_DP, 1.0_DP) * xg_nonlop%weight
1142 :
1143 865236 : call xgBlock_reverseMap(xg_nonlop%ffnl_gather_k%self,ffnl_gather_k_)
1144 :
1145 1273380 : select case(xg_nonlop%space_pw)
1146 :
1147 : case (SPACE_C)
1148 :
1149 408144 : call xgBlock_reverseMap(projs_otf,projectors_k_)
1150 408144 : call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_)
1151 408144 : shift_itypat=0
1152 408144 : shift_itypat_nlmn=0
1153 : !$omp parallel default (none) &
1154 : !$omp& shared(xg_nonlop,ph3d_gather_k_,ffnl_gather_k_,projectors_k_), &
1155 : !$omp& firstprivate(ntypat,npw_k,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
1156 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw,ffnl_ipw,icol)
1157 1224432 : do itypat = 1, ntypat
1158 816288 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
1159 816288 : nattyp_i = xg_nonlop%nattyp(itypat)
1160 1224432 : if (nattyp_i>0) then
1161 : !! projectors = 4pi/sqrt(ucvol)* conj(ph3d) * ffnl * (-i)^l
1162 : !$omp do collapse(3)
1163 1632576 : do ia = 1, nattyp_i
1164 8162880 : do ilmn=1,nlmn
1165 239950512 : do ipw=1,npw_k
1166 232603920 : iatom = ia + shift_itypat
1167 232603920 : il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
1168 232603920 : ph3d_ipw = ph3d_gather_k_(ipw+shift_ipw,iatom)
1169 232603920 : ffnl_ipw = ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max)
1170 : !
1171 232603920 : icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
1172 239134224 : projectors_k_(ipw,icol) = cil(il) * conjg(ph3d_ipw) * ffnl_ipw
1173 : end do
1174 : end do
1175 : end do
1176 : !$omp end do
1177 816288 : shift_itypat = shift_itypat + nattyp_i
1178 816288 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
1179 : end if
1180 : end do
1181 : !$omp end parallel
1182 :
1183 : case(SPACE_CR)
1184 :
1185 457092 : call xgBlock_reverseMap(projs_otf,projectors_k_real)
1186 457092 : call xgBlock_reverseMap(xg_nonlop%ph3d_gather_k%self,ph3d_gather_k_real)
1187 457092 : shift_itypat=0
1188 457092 : shift_itypat_nlmn=0
1189 : !$omp parallel default (none) &
1190 : !$omp& shared(xg_nonlop,ph3d_gather_k_real,ffnl_gather_k_,projectors_k_real), &
1191 : !$omp& firstprivate(ntypat,npw_k,shift_ipw,shift_itypat,shift_itypat_nlmn,cil), &
1192 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,ipw,iatom,il,ph3d_ipw_r,ffnl_ipw,icol,ctmp)
1193 1371276 : do itypat = 1, ntypat
1194 914184 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
1195 914184 : nattyp_i = xg_nonlop%nattyp(itypat)
1196 1371276 : if (nattyp_i>0) then
1197 : !! projectors = 4pi/sqrt(ucvol)* conj(ph3d) * ffnl * (-i)^l
1198 : !$omp do collapse(3)
1199 1828368 : do ia = 1, nattyp_i
1200 14977548 : do ilmn=1,nlmn
1201 247695219 : do ipw=1,npw_k
1202 233631855 : iatom = ia + shift_itypat
1203 233631855 : il=mod(xg_nonlop%indlmn(1,ilmn,itypat),4)+1
1204 233631855 : ph3d_ipw_r(1) = ph3d_gather_k_real(2*(ipw+shift_ipw)-1,iatom)
1205 233631855 : ph3d_ipw_r(2) = ph3d_gather_k_real(2*(ipw+shift_ipw) ,iatom)
1206 233631855 : ffnl_ipw = ffnl_gather_k_(ipw+shift_ipw,ilmn+(itypat-1)*xg_nonlop%nlmn_max)
1207 : !
1208 233631855 : ctmp = cmplx( ph3d_ipw_r(1), ph3d_ipw_r(2), kind=DP)
1209 233631855 : ctmp = cil(il) * conjg(ctmp) * ffnl_ipw
1210 233631855 : icol = ilmn + (ia-1)*nlmn + shift_itypat_nlmn
1211 233631855 : projectors_k_real(2*ipw-1,icol) = dble(ctmp)
1212 246781035 : projectors_k_real(2*ipw ,icol) = dimag(ctmp)
1213 : end do
1214 : end do
1215 : end do
1216 : !$omp end do
1217 914184 : shift_itypat = shift_itypat + nattyp_i
1218 914184 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
1219 : end if
1220 : end do
1221 : !$omp end parallel
1222 :
1223 : case default
1224 865236 : ABI_ERROR("Wrong space")
1225 :
1226 : end select
1227 :
1228 865236 : end subroutine xg_nonlop_compute_projs_otf
1229 : !!***
1230 :
1231 18244 : subroutine xg_nonlop_make_k(xg_nonlop,ikpt,istwf_k,me_g0,me_g0_fft,npw_k,ffnl_k,ph3d_k,kpg_k,compute_proj,&
1232 : compute_invS_approx,compute_gram)
1233 :
1234 : type(xg_nonlop_t),intent(inout) :: xg_nonlop
1235 :
1236 : logical ,intent(in) :: compute_proj
1237 : integer ,intent(in) :: ikpt
1238 : integer ,intent(in) :: istwf_k
1239 : integer, intent(in) :: me_g0
1240 : integer, intent(in) :: me_g0_fft
1241 : integer, intent(in) :: npw_k
1242 : real(dp), intent(in), target :: ffnl_k(:,:,:,:)
1243 : real(dp), intent(in), target :: ph3d_k(:,:,:)
1244 : real(dp), intent(in), target :: kpg_k(:,:)
1245 : logical ,optional,intent(in) :: compute_invS_approx
1246 : logical ,optional,intent(in) :: compute_gram
1247 :
1248 : logical :: compute_gram_,compute_invS_approx_
1249 18244 : real(dp),pointer :: gram_proj_k_(:,:),Sijm1_(:,:)
1250 : integer :: ierr, iblock, shift, shiftc, shift_sij, shift_itypat, itypat, ilmn, jlmn, nlmn, nlmn_max, ia
1251 : integer :: cplex,nattyp_i,ntypat,ncols,nmpi,me_g0_loc,me_g0_fft_loc,space_cprj
1252 : !integer :: cols,cond
1253 : real(dp) :: tsec(2)
1254 : type(xg_t) :: work
1255 : type(xgBlock_t) :: projs,invSij_approx_k_itypat,Sijm1_itypat
1256 :
1257 : ! *************************************************************************
1258 :
1259 18244 : call timab(tim_make_k,1,tsec)
1260 :
1261 18244 : me_g0_loc = -1
1262 18244 : me_g0_fft_loc = -1
1263 18244 : if (istwf_k==1) then
1264 10357 : xg_nonlop%cplex=2
1265 10357 : xg_nonlop%space_pw=SPACE_C
1266 10357 : xg_nonlop%space_cprj=SPACE_C
1267 : else ! istwf_k>1
1268 7887 : xg_nonlop%cplex=1
1269 7887 : xg_nonlop%space_pw=SPACE_CR
1270 7887 : xg_nonlop%space_cprj=SPACE_R
1271 7887 : me_g0_loc = 0
1272 7887 : me_g0_fft_loc = 0
1273 7887 : if (istwf_k==2.and.me_g0==1) then
1274 431 : me_g0_loc = me_g0
1275 431 : me_g0_fft_loc = me_g0_fft
1276 : end if
1277 : end if
1278 :
1279 18244 : cplex = xg_nonlop%cplex
1280 18244 : space_cprj = xg_nonlop%space_cprj
1281 :
1282 18244 : xg_nonlop%npw_k = npw_k
1283 :
1284 73416 : xg_nonlop%l_npw_k(:) = 0
1285 18244 : xg_nonlop%l_npw_k(xg_nonlop%me_band+1) = npw_k
1286 18244 : call xmpi_sum(xg_nonlop%l_npw_k,xg_nonlop%comm_band,ierr)
1287 :
1288 73416 : xg_nonlop%total_npw_k = sum(xg_nonlop%l_npw_k)
1289 73416 : xg_nonlop%max_npw_k = maxval(xg_nonlop%l_npw_k)
1290 :
1291 18244 : xg_nonlop%l_shift_npw_k(1) = 0
1292 18244 : nmpi = xmpi_comm_size(xg_nonlop%comm_band)
1293 55172 : do iblock=2,nmpi
1294 55172 : xg_nonlop%l_shift_npw_k(iblock) = xg_nonlop%l_shift_npw_k(iblock-1) + xg_nonlop%l_npw_k(iblock-1)
1295 : end do
1296 :
1297 18244 : ntypat = xg_nonlop%ntypat
1298 18244 : nlmn_max = xg_nonlop%nlmn_max
1299 :
1300 18244 : xg_nonlop%ph3d_k => ph3d_k
1301 18244 : xg_nonlop%ffnl_k => ffnl_k
1302 :
1303 18244 : xg_nonlop%kpg_k => kpg_k
1304 :
1305 18244 : xg_nonlop%projectors_k => xg_nonlop%projectors(ikpt)
1306 18244 : if (xg_nonlop%option==0) then
1307 17220 : xg_nonlop%ffnl_gather_k => xg_nonlop%ffnl_gather(ikpt)
1308 17220 : xg_nonlop%ph3d_gather_k => xg_nonlop%ph3d_gather(ikpt)
1309 : end if
1310 :
1311 18244 : if (xg_nonlop%paw) then
1312 15172 : xg_nonlop%gram_proj_k => xg_nonlop%gram_proj(ikpt)
1313 15172 : xg_nonlop%invSij_approx_k => xg_nonlop%invSij_approx(ikpt)
1314 : end if
1315 :
1316 18244 : if (compute_proj) then
1317 :
1318 : call xg_init(xg_nonlop%projectors_k,xg_nonlop%space_pw,npw_k,xg_nonlop%cprjdim,&
1319 2320 : xg_nonlop%comm_band,me_g0=me_g0_loc)
1320 :
1321 2320 : if (xg_nonlop%option==0) then
1322 2192 : call xg_init(xg_nonlop%ffnl_gather_k,SPACE_R,xg_nonlop%total_npw_k,nlmn_max*ntypat,xmpi_comm_null)
1323 : call xg_init(xg_nonlop%ph3d_gather_k,xg_nonlop%space_pw,xg_nonlop%total_npw_k,xg_nonlop%natom,&
1324 2192 : xmpi_comm_null,me_g0=me_g0_fft_loc)
1325 : end if
1326 :
1327 2320 : call xg_nonlop_compute_projs(xg_nonlop)
1328 :
1329 2320 : compute_invS_approx_=.false.
1330 2320 : if (present(compute_invS_approx)) compute_invS_approx_ = compute_invS_approx
1331 1160 : if (compute_invS_approx_) then
1332 :
1333 770 : if (.not.xg_nonlop%paw) then
1334 0 : ABI_ERROR('Not implemented with paw=False.')
1335 : end if
1336 :
1337 : !invSij_approx_k is allocated here as space_pw depends on k-point
1338 770 : call xg_init(xg_nonlop%invSij_approx_k,space_cprj,nlmn_max,nlmn_max*ntypat,xmpi_comm_self)
1339 :
1340 770 : shift_itypat=1
1341 2334 : do itypat = 1, ntypat
1342 1564 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
1343 1564 : nattyp_i = xg_nonlop%nattyp(itypat)
1344 2334 : if (nattyp_i>0) then
1345 1540 : shift_sij = 1+(itypat-1)*nlmn_max
1346 1540 : call xgBlock_setBlock(xg_nonlop%projectors_k%self,projs,npw_k,nlmn,fcol=shift_itypat)
1347 1540 : call xg_setBlock(xg_nonlop%invSij_approx_k,invSij_approx_k_itypat,nlmn,nlmn,fcol=shift_sij)
1348 1540 : call xg_setBlock(xg_nonlop%Sijm1,Sijm1_itypat,nlmn,nlmn,fcol=shift_sij)
1349 1540 : if (space_cprj==SPACE_R) then
1350 496 : call xgBlock_copy(Sijm1_itypat,invSij_approx_k_itypat)
1351 : else
1352 1044 : call xgBlock_r2c(Sijm1_itypat,invSij_approx_k_itypat,1)
1353 : end if
1354 1540 : call xg_init(work,space_cprj,nlmn,nlmn,xmpi_comm_self)
1355 1540 : call xgBlock_gemm('t','n',1.0d0,projs,projs,0.0d0,work%self,comm=xg_nonlop%comm_band)
1356 1540 : call xgBlock_add(invSij_approx_k_itypat,work%self)
1357 1540 : call xgBlock_invert_sy(invSij_approx_k_itypat,work%self)
1358 1540 : call xg_free(work)
1359 1540 : shift_itypat = shift_itypat + nlmn*nattyp_i
1360 : end if
1361 : end do
1362 :
1363 : end if
1364 :
1365 2320 : compute_gram_=.false.
1366 2320 : if (present(compute_gram)) compute_gram_ = compute_gram
1367 1160 : if (compute_gram_) then
1368 :
1369 770 : if (.not.xg_nonlop%paw) then
1370 0 : ABI_ERROR('Not implemented with paw=False.')
1371 : end if
1372 770 : cplex=xg_nonlop%cplex
1373 770 : ncols = xg_nonlop%cprjdim
1374 770 : call xg_init(xg_nonlop%gram_proj_k,space_cprj,ncols,ncols,xmpi_comm_self)
1375 770 : projs = xg_nonlop%projectors_k%self
1376 770 : call xgBlock_gemm('t','n',1.0d0,projs,projs,0.0d0,xg_nonlop%gram_proj_k%self,comm=xg_nonlop%comm_band)
1377 770 : call xgBlock_reverseMap(xg_nonlop%gram_proj_k%self,gram_proj_k_)
1378 770 : shift=0
1379 770 : shiftc=0
1380 2334 : do itypat = 1, ntypat
1381 1564 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
1382 1564 : nattyp_i = xg_nonlop%nattyp(itypat)
1383 2334 : if (nattyp_i>0) then
1384 1540 : shift_sij = 1+(itypat-1)*nlmn_max
1385 1540 : call xg_setBlock(xg_nonlop%Sijm1,Sijm1_itypat,nlmn,nlmn,fcol=shift_sij)
1386 1540 : call xgBlock_reverseMap(Sijm1_itypat,Sijm1_)
1387 3096 : do ia = 1, nattyp_i
1388 14084 : do jlmn=1,nlmn
1389 115748 : do ilmn=1,nlmn
1390 : gram_proj_k_(shiftc+cplex*(ilmn-1)+1,shift+jlmn) = gram_proj_k_(shiftc+cplex*(ilmn-1)+1,shift+jlmn) &
1391 114192 : & + Sijm1_(ilmn,jlmn)
1392 : end do
1393 : end do
1394 1556 : shift = shift + nlmn
1395 3096 : shiftc = shiftc + cplex*nlmn
1396 : end do
1397 : end if
1398 : end do
1399 :
1400 : !ITEST
1401 : !write(903,*) 'make_cprj, compute gram', cols, space_cprj==SPACE_C
1402 : !call xgBlock_hermitian_pd_cond(xg_nonlop%gram_proj_k%self, cols, cond)
1403 : !write(903,*) 'cond(B)=', cond
1404 : !flush(903)
1405 : !ITEST
1406 :
1407 : end if
1408 :
1409 : end if ! compute_proj
1410 :
1411 18244 : call timab(tim_make_k,2,tsec)
1412 :
1413 18244 : end subroutine xg_nonlop_make_k
1414 : !!***
1415 :
1416 679140 : subroutine xg_nonlop_set_nmpi(xg_nonlop,X,cprjX,nmpi,blocksize,fft_representation)
1417 :
1418 : type(xg_nonlop_t), intent(in) :: xg_nonlop
1419 : type(xgBlock_t), intent(in) :: X
1420 : type(xgBlock_t), intent(in) :: cprjX
1421 : integer, intent(out) :: blocksize,nmpi
1422 : logical, intent(out) :: fft_representation
1423 :
1424 : integer :: nspinor,npw
1425 : type(xgBlock_t) :: projs
1426 :
1427 679140 : if (.not.associated(xg_nonlop%projectors_k)) then
1428 0 : ABI_ERROR('projectors_k should be associated')
1429 : end if
1430 :
1431 679140 : projs = xg_nonlop%projectors_k%self
1432 :
1433 679140 : npw = xg_nonlop%npw_k
1434 679140 : nspinor = xg_nonlop%nspinor
1435 679140 : blocksize = cols(cprjX)
1436 :
1437 : ! Check projector sizes
1438 679140 : if (npw/=rows(projs)) then
1439 0 : ABI_ERROR('npw/=rows(projs)')
1440 : end if
1441 679140 : if (xg_nonlop%cprjdim/=cols(projs)) then
1442 0 : ABI_ERROR('cols(projs)/=cprjdim')
1443 : end if
1444 : ! Check cprj sizes
1445 679140 : if (rows(cprjX)/=xg_nonlop%cprjdim) then
1446 0 : ABI_ERROR('rows(cprjX)/=cprjdim')
1447 : end if
1448 : ! rows(projs), cols(projs) and rows(cprj) are checked.
1449 : ! Now we check : rows(X),cols(X) and cols(cprj) depending on mpi
1450 679140 : nmpi = xmpi_comm_size(comm(cprjX))
1451 679140 : if (nmpi==1) then ! sequential
1452 196864 : if (xmpi_comm_size(comm(X))/=1) then
1453 0 : ABI_ERROR('size(comm(X))/=1')
1454 : end if
1455 196864 : if (rows(X)/=npw*nspinor) then
1456 0 : ABI_ERROR('rows(X)/=npw*nspinor')
1457 : end if
1458 196864 : if (cols(X)*nspinor/=blocksize) then
1459 0 : ABI_ERROR('cols(cprjX)/=cols(X)*nspinor')
1460 : end if
1461 : else ! MPI
1462 : ! FFT representation (X have all rows, cols are distributed)
1463 482276 : if (rows(X)==xg_nonlop%total_npw_k*nspinor) then
1464 343900 : fft_representation = .True.
1465 343900 : if (xmpi_comm_size(comm(X))/=1) then
1466 0 : ABI_ERROR('size(comm(X))/=1')
1467 : end if
1468 343900 : if (cols(X)*nspinor/=blocksize) then
1469 0 : ABI_ERROR('cols(cprjX)/=cols(X)*nspinor')
1470 : end if
1471 : ! Linalg representation (X have all cols, rows are distributed)
1472 : else
1473 138376 : fft_representation = .False.
1474 138376 : if (comm(X)/=comm(cprjX)) then
1475 0 : ABI_ERROR('comm(X)/=comm(cprjX)')
1476 : end if
1477 138376 : if (rows(X)/=npw*nspinor) then
1478 0 : ABI_ERROR('rows(X)/=npw*nspinor')
1479 : end if
1480 138376 : if (cols(X)*nspinor/=blocksize*nmpi) then
1481 0 : ABI_ERROR('cols(cprjX)*nmpi/=cols(X)*nspinor')
1482 : end if
1483 : end if
1484 : end if
1485 :
1486 679140 : end subroutine xg_nonlop_set_nmpi
1487 :
1488 : !!****f* m_xg_nonlop/xg_nonlop_getcprj
1489 : !! NAME
1490 : !!
1491 : !! FUNCTION
1492 : !!
1493 : !! INPUTS
1494 : !!
1495 728616 : subroutine xg_nonlop_getcprj(xg_nonlop,X,cprjX,work_mpi)
1496 :
1497 : type(xg_nonlop_t), intent(in) :: xg_nonlop
1498 : type(xgBlock_t) , intent(in ) :: X
1499 : type(xgBlock_t) , intent(inout) :: cprjX,work_mpi
1500 :
1501 : real(dp) :: tsec(2)
1502 : integer :: ierr,iblock,nmpi,npw,npw_max,blocksize,nspinor,shift,shift_row
1503 : integer :: source,dest,tag,request,me_band,me_g0_loc
1504 : logical :: fft_representation
1505 : type(xgBlock_t) :: X_block,X_spinor,projs,work_mpi_npw
1506 : type(xg_t) :: work_npw
1507 :
1508 364308 : call timab(tim_getcprj,1,tsec)
1509 :
1510 364308 : call xg_nonlop_set_nmpi(xg_nonlop,X,cprjX,nmpi,blocksize,fft_representation)
1511 :
1512 364308 : nspinor = xg_nonlop%nspinor
1513 364308 : projs = xg_nonlop%projectors_k%self
1514 :
1515 364308 : call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
1516 :
1517 364308 : if (nmpi==1) then
1518 :
1519 106394 : call timab(tim_getcprj_gemm,1,tsec)
1520 106394 : call xgBlock_gemm('t','n',1.0d0,projs,X_spinor,0.d0,cprjX)
1521 106394 : call timab(tim_getcprj_gemm,2,tsec)
1522 :
1523 : else
1524 :
1525 257914 : me_band=xg_nonlop%me_band
1526 :
1527 257914 : if (fft_representation) then ! FFT representation (X have all rows, cols are distributed)
1528 :
1529 177488 : npw_max = xg_nonlop%max_npw_k
1530 :
1531 177488 : if (rows(work_mpi)/=npw_max) then
1532 0 : ABI_ERROR('rows(work)/=npw_max')
1533 : end if
1534 177488 : if (cols(work_mpi)/=xg_nonlop%cprjdim) then
1535 0 : ABI_ERROR('rows(work)/=cprjdim')
1536 : end if
1537 :
1538 : ! npw_max=npw_tot/Nmpi and blocksize=nband/Nmpi so size(work_npw) ~ 1/Nmpi^2
1539 177488 : call xg_init(work_npw,xg_nonlop%space_pw,npw_max,blocksize,xmpi_comm_null,me_g0=me_g0(X))
1540 :
1541 859696 : do iblock=1,nmpi
1542 :
1543 859696 : if (iblock==1) then
1544 177488 : npw = xg_nonlop%l_npw_k(me_band+1)
1545 177488 : shift_row = xg_nonlop%l_shift_npw_k(me_band+1)
1546 177488 : call xg_setBlock(work_npw,X_block,npw,blocksize)
1547 :
1548 177488 : call timab(tim_getcprj_copy,1,tsec)
1549 177488 : call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
1550 177488 : call timab(tim_getcprj_copy,2,tsec)
1551 :
1552 177488 : call timab(tim_getcprj_gemm,1,tsec)
1553 177488 : call xgBlock_gemm('t','n',1.0d0,projs,X_block,0.d0,cprjX)
1554 177488 : call timab(tim_getcprj_gemm,2,tsec)
1555 :
1556 : else
1557 504720 : tag = iblock
1558 504720 : dest = mod(me_band-(iblock-1),nmpi)
1559 504720 : if (dest<0) dest=dest+nmpi
1560 :
1561 504720 : if (xg_nonlop%option==1) then
1562 55488 : call timab(tim_getcprj_mpi,1,tsec)
1563 55488 : call xgBlock_mpi_isend(projs,dest,tag,request,comm=xg_nonlop%comm_band)
1564 55488 : call timab(tim_getcprj_mpi,2,tsec)
1565 : end if
1566 :
1567 504720 : source = mod(me_band+(iblock-1),nmpi)
1568 504720 : npw = xg_nonlop%l_npw_k(source+1)
1569 504720 : shift_row = xg_nonlop%l_shift_npw_k(source+1)
1570 504720 : me_g0_loc = -1
1571 504720 : if (xg_nonlop%space_pw==SPACE_CR) then
1572 247608 : me_g0_loc = me_g0(X)
1573 247608 : if (shift_row>0) me_g0_loc = 0
1574 : end if
1575 504720 : call xg_setBlock(work_npw,X_block,npw,blocksize)
1576 :
1577 504720 : call timab(tim_getcprj_copy,1,tsec)
1578 504720 : call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
1579 504720 : call timab(tim_getcprj_copy,2,tsec)
1580 :
1581 504720 : call xgBlock_setBlock(work_mpi,work_mpi_npw,npw_max,xg_nonlop%cprjdim)
1582 504720 : call xgBlock_free_reshape(work_mpi_npw,npw,xg_nonlop%cprjdim,new_me_g0=me_g0_loc)
1583 :
1584 504720 : if (xg_nonlop%option==1) then
1585 55488 : call timab(tim_getcprj_mpi,1,tsec)
1586 55488 : call xgBlock_mpi_recv(work_mpi_npw,source,tag,comm=xg_nonlop%comm_band)
1587 55488 : call timab(tim_getcprj_mpi,2,tsec)
1588 449232 : else if (xg_nonlop%option==0) then
1589 449232 : call timab(tim_getcprj_otf,1,tsec)
1590 449232 : call xg_nonlop_compute_projs_otf(xg_nonlop,work_mpi_npw,source)
1591 449232 : call timab(tim_getcprj_otf,2,tsec)
1592 : else
1593 0 : ABI_ERROR("Wrong xg_nonlop%option")
1594 : end if
1595 :
1596 504720 : call timab(tim_getcprj_gemm,1,tsec)
1597 504720 : call xgBlock_gemm('t','n',1.0d0,work_mpi_npw,X_block,1.d0,cprjX)
1598 504720 : call timab(tim_getcprj_gemm,2,tsec)
1599 :
1600 504720 : if (xg_nonlop%option==1) then
1601 55488 : call timab(tim_getcprj_mpi,1,tsec)
1602 55488 : call xmpi_wait(request,ierr)
1603 55488 : call timab(tim_getcprj_mpi,2,tsec)
1604 : end if
1605 :
1606 : end if
1607 :
1608 : end do
1609 :
1610 177488 : call xg_free(work_npw)
1611 :
1612 : else ! Linalg representation (X have all cols, rows are distributed)
1613 :
1614 80426 : call xgBlock_check(cprjX,work_mpi)
1615 :
1616 387078 : do iblock=1,nmpi
1617 306652 : shift=1+(iblock-1)*blocksize
1618 306652 : call xgBlock_setBlock(X_spinor,X_block,rows(X_spinor),blocksize,fcol=shift)
1619 :
1620 306652 : call timab(tim_getcprj_gemm,1,tsec)
1621 306652 : call xgBlock_gemm('t','n',1.0d0,projs,X_block,0.d0,work_mpi)
1622 306652 : call timab(tim_getcprj_gemm,2,tsec)
1623 : ! We do the mpi sum outside xgBlock_gemm just to include the timing in tim_getcprj_mpi,
1624 : ! (instead of tim_gemm_mpi).
1625 306652 : call timab(tim_getcprj_mpi,1,tsec)
1626 306652 : call xgBlock_mpi_sum(work_mpi,comm=xg_nonlop%comm_band)
1627 306652 : call timab(tim_getcprj_mpi,2,tsec)
1628 :
1629 387078 : if (me_band==iblock-1) then
1630 80426 : call timab(tim_getcprj_copy,1,tsec)
1631 80426 : call xgBlock_copy(work_mpi,cprjX)
1632 80426 : call timab(tim_getcprj_copy,2,tsec)
1633 : end if
1634 : end do
1635 :
1636 : end if
1637 :
1638 : end if
1639 :
1640 364308 : call timab(tim_getcprj,2,tsec)
1641 :
1642 364308 : end subroutine xg_nonlop_getcprj
1643 : !!***
1644 :
1645 : !!****f* m_xg_nonlop/xg_nonlop_getcprj_deriv
1646 : !! NAME
1647 : !!
1648 : !! FUNCTION
1649 : !!
1650 : !! INPUTS
1651 : !!
1652 19440 : subroutine xg_nonlop_getcprj_deriv(xg_nonlop,X,cprjX,work_mpi,option)
1653 :
1654 : type(xg_nonlop_t), intent(in) :: xg_nonlop
1655 : type(xgBlock_t) , intent(in) :: X
1656 : integer , intent(in) :: option
1657 : type(xgBlock_t) , intent(inout) :: cprjX,work_mpi
1658 :
1659 : ! real(dp) :: tsec(2)
1660 : integer :: iblock,nmpi,npw,blocksize,nspinor,shift
1661 : integer :: me_band,proj_size
1662 : type(xgBlock_t) :: X_block,X_spinor
1663 : type(xg_t) :: projs_deriv
1664 :
1665 : ! call timab(tim_getcprj,1,tsec)
1666 :
1667 19440 : npw = xg_nonlop%npw_k
1668 19440 : nspinor = xg_nonlop%nspinor
1669 19440 : blocksize = cols(cprjX)
1670 :
1671 19440 : if (option==DERIV_ATOM) then
1672 18300 : proj_size = 3*xg_nonlop%cprjdim
1673 1140 : else if (option==DERIV_STRESS) then
1674 1140 : proj_size = 6*xg_nonlop%cprjdim
1675 : else
1676 0 : ABI_ERROR('Bad option')
1677 : end if
1678 : ! Check cprj sizes
1679 19440 : if (rows(cprjX)/=proj_size) then
1680 0 : ABI_ERROR('rows(cprjX)/=proj_size')
1681 : end if
1682 : ! Now we check : rows(X),cols(X) and cols(cprj) depending on mpi
1683 19440 : nmpi = xmpi_comm_size(comm(cprjX))
1684 19440 : if (nmpi==1) then ! sequential
1685 6496 : if (xmpi_comm_size(comm(X))/=1) then
1686 0 : ABI_ERROR('size(comm(X))/=1')
1687 : end if
1688 6496 : if (rows(X)/=npw*nspinor) then
1689 0 : ABI_ERROR('rows(X)/=npw*nspinor')
1690 : end if
1691 6496 : if (cols(X)*nspinor/=blocksize) then
1692 0 : ABI_ERROR('cols(cprjX)/=cols(X)*nspinor')
1693 : end if
1694 : else ! MPI
1695 : ! Linalg representation (X have all cols, rows are distributed)
1696 12944 : if (comm(X)/=comm(cprjX)) then
1697 0 : ABI_ERROR('comm(X)/=comm(cprjX)')
1698 : end if
1699 12944 : if (rows(X)/=npw*nspinor) then
1700 0 : ABI_ERROR('rows(X)/=npw*nspinor')
1701 : end if
1702 12944 : if (cols(X)*nspinor/=blocksize*nmpi) then
1703 0 : ABI_ERROR('cols(cprjX)*nmpi/=cols(X)*nspinor')
1704 : end if
1705 : end if
1706 :
1707 19440 : call xg_init(projs_deriv,xg_nonlop%space_pw,npw,proj_size,comm=xg_nonlop%comm_band,me_g0=me_g0(X))
1708 :
1709 18300 : select case (option)
1710 : case (DERIV_ATOM)
1711 18300 : call xg_nonlop_compute_projs_deriv_atom(xg_nonlop,projs_deriv%self)
1712 : case (DERIV_STRESS)
1713 19440 : call xg_nonlop_compute_projs_deriv_stress(xg_nonlop,projs_deriv%self)
1714 : end select
1715 :
1716 19440 : call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
1717 :
1718 19440 : if (nmpi==1) then
1719 :
1720 : ! call timab(tim_getcprj_gemm,1,tsec)
1721 6496 : call xgBlock_gemm('t','n',1.0d0,projs_deriv%self,X_spinor,0.d0,cprjX)
1722 : ! call timab(tim_getcprj_gemm,2,tsec)
1723 :
1724 : else
1725 :
1726 12944 : me_band=xg_nonlop%me_band
1727 :
1728 12944 : call xgBlock_check(cprjX,work_mpi)
1729 :
1730 62128 : do iblock=1,nmpi
1731 49184 : shift=1+(iblock-1)*blocksize
1732 49184 : call xgBlock_setBlock(X_spinor,X_block,rows(X_spinor),blocksize,fcol=shift)
1733 :
1734 : ! call timab(tim_getcprj_gemm,1,tsec)
1735 49184 : call xgBlock_gemm('t','n',1.0d0,projs_deriv%self,X_block,0.d0,work_mpi)
1736 : ! call timab(tim_getcprj_gemm,2,tsec)
1737 : ! We do the mpi sum outside xgBlock_gemm just to include the timing in tim_getcprj_mpi,
1738 : ! (instead of tim_gemm_mpi).
1739 : ! call timab(tim_getcprj_mpi,1,tsec)
1740 49184 : call xgBlock_mpi_sum(work_mpi,comm=xg_nonlop%comm_band)
1741 : ! call timab(tim_getcprj_mpi,2,tsec)
1742 :
1743 62128 : if (me_band==iblock-1) then
1744 : ! call timab(tim_getcprj_copy,1,tsec)
1745 12944 : call xgBlock_copy(work_mpi,cprjX)
1746 : ! call timab(tim_getcprj_copy,2,tsec)
1747 : end if
1748 : end do
1749 :
1750 : end if
1751 :
1752 19440 : call xg_free(projs_deriv)
1753 : ! call timab(tim_getcprj,2,tsec)
1754 :
1755 19440 : end subroutine xg_nonlop_getcprj_deriv
1756 : !!***
1757 :
1758 629664 : subroutine xg_nonlop_apply_prj(xg_nonlop,cprjX,X,work_mpi)
1759 :
1760 : type(xg_nonlop_t), intent(in) :: xg_nonlop
1761 : type(xgBlock_t), intent(in) :: cprjX
1762 : type(xgBlock_t), intent(inout) :: X,work_mpi
1763 :
1764 : logical :: fft_representation
1765 : integer :: nmpi,npw,blocksize,iblock,shift_col,nspinor!,nband,npw
1766 : integer :: me_band,shift_row,npw_max
1767 : integer :: ierr,source,dest,tag,request
1768 : real(dp) :: tsec(2)
1769 : type(xgBlock_t) :: projs
1770 : type(xgBlock_t) :: X_spinor,X_block,work_mpi_npw
1771 : type(xg_t) :: work_npw
1772 :
1773 314832 : call timab(tim_apply_prj,1,tsec)
1774 :
1775 314832 : call xg_nonlop_set_nmpi(xg_nonlop,X,cprjX,nmpi,blocksize,fft_representation)
1776 :
1777 314832 : projs = xg_nonlop%projectors_k%self
1778 :
1779 314832 : nspinor = xg_nonlop%nspinor
1780 314832 : call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
1781 :
1782 314832 : if (nmpi==1) then
1783 :
1784 90470 : call timab(tim_apply_prj_gemm,1,tsec)
1785 90470 : call xgBlock_gemm('n','n',1.0d0,projs,cprjX,1.d0,X_spinor)
1786 90470 : call timab(tim_apply_prj_gemm,2,tsec)
1787 :
1788 : else
1789 :
1790 224362 : me_band = xg_nonlop%me_band
1791 :
1792 224362 : if (fft_representation) then ! FFT representation (X have all rows, cols are distributed)
1793 :
1794 166412 : npw_max = xg_nonlop%max_npw_k
1795 :
1796 166412 : if (rows(work_mpi)/=npw_max) then
1797 0 : ABI_ERROR('rows(work)/=npw_max')
1798 : end if
1799 166412 : if (cols(work_mpi)/=xg_nonlop%cprjdim) then
1800 0 : ABI_ERROR('rows(work)/=cprjdim')
1801 : end if
1802 :
1803 : ! npw_max=npw_tot/Nmpi and blocksize=nband/Nmpi so size(work_npw) ~ 1/Nmpi^2
1804 166412 : call xg_init(work_npw,xg_nonlop%space_pw,npw_max,blocksize,xmpi_comm_null)
1805 :
1806 804316 : do iblock=1,nmpi
1807 :
1808 804316 : if (iblock==1) then
1809 166412 : npw = xg_nonlop%l_npw_k(me_band+1)
1810 166412 : call xg_setBlock(work_npw,X_block,npw,blocksize)
1811 166412 : shift_row = xg_nonlop%l_shift_npw_k(me_band+1)
1812 :
1813 166412 : call timab(tim_apply_prj_copy,1,tsec)
1814 166412 : call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
1815 166412 : call timab(tim_apply_prj_copy,2,tsec)
1816 :
1817 166412 : call timab(tim_apply_prj_gemm,1,tsec)
1818 166412 : call xgBlock_gemm('n','n',1.0d0,projs,cprjX,1.d0,X_block)
1819 166412 : call timab(tim_apply_prj_gemm,2,tsec)
1820 :
1821 166412 : call timab(tim_apply_prj_copy,1,tsec)
1822 166412 : call xgBlock_partialcopy(X_block,X_spinor,shift_row,0,SMALL2BIG)
1823 166412 : call timab(tim_apply_prj_copy,2,tsec)
1824 : else
1825 471492 : tag = iblock
1826 471492 : dest = mod(me_band-(iblock-1),nmpi)
1827 471492 : if (dest<0) dest=dest+nmpi
1828 :
1829 471492 : if (xg_nonlop%option==1) then
1830 55488 : call timab(tim_apply_prj_mpi,1,tsec)
1831 55488 : call xgBlock_mpi_isend(projs,dest,tag,request,comm=xg_nonlop%comm_band)
1832 55488 : call timab(tim_apply_prj_mpi,2,tsec)
1833 : end if
1834 :
1835 471492 : source = mod(me_band+(iblock-1),nmpi)
1836 471492 : npw = xg_nonlop%l_npw_k(source+1)
1837 471492 : call xg_setBlock(work_npw,X_block,npw,blocksize)
1838 471492 : shift_row = xg_nonlop%l_shift_npw_k(source+1)
1839 :
1840 471492 : call timab(tim_apply_prj_copy,1,tsec)
1841 471492 : call xgBlock_partialcopy(X_spinor,X_block,shift_row,0,BIG2SMALL)
1842 471492 : call timab(tim_apply_prj_copy,2,tsec)
1843 :
1844 471492 : call xgBlock_setBlock(work_mpi,work_mpi_npw,npw_max,xg_nonlop%cprjdim)
1845 471492 : call xgBlock_free_reshape(work_mpi_npw,npw,xg_nonlop%cprjdim)
1846 :
1847 471492 : if (xg_nonlop%option==1) then
1848 55488 : call timab(tim_apply_prj_mpi,1,tsec)
1849 55488 : call xgBlock_mpi_recv(work_mpi_npw,source,tag,comm=xg_nonlop%comm_band)
1850 55488 : call timab(tim_apply_prj_mpi,2,tsec)
1851 416004 : else if (xg_nonlop%option==0) then
1852 416004 : call timab(tim_apply_prj_otf,1,tsec)
1853 416004 : call xg_nonlop_compute_projs_otf(xg_nonlop,work_mpi_npw,source)
1854 416004 : call timab(tim_apply_prj_otf,2,tsec)
1855 : else
1856 0 : ABI_ERROR("Wrong xg_nonlop%option")
1857 : end if
1858 :
1859 471492 : call timab(tim_apply_prj_gemm,1,tsec)
1860 471492 : call xgBlock_gemm('n','n',1.0d0,work_mpi_npw,cprjX,1.d0,X_block)
1861 471492 : call timab(tim_apply_prj_gemm,2,tsec)
1862 :
1863 471492 : call timab(tim_apply_prj_copy,1,tsec)
1864 471492 : call xgBlock_partialcopy(X_block,X_spinor,shift_row,0,SMALL2BIG)
1865 471492 : call timab(tim_apply_prj_copy,2,tsec)
1866 :
1867 471492 : if (xg_nonlop%option==1) then
1868 55488 : call timab(tim_apply_prj_mpi,1,tsec)
1869 55488 : call xmpi_wait(request,ierr)
1870 55488 : call timab(tim_apply_prj_mpi,2,tsec)
1871 : end if
1872 : end if
1873 :
1874 : end do
1875 :
1876 166412 : call xg_free(work_npw)
1877 :
1878 : else ! Linalg representation (X have all cols, rows are distributed)
1879 :
1880 57950 : call xgBlock_check(cprjX,work_mpi)
1881 :
1882 278762 : do iblock=1,nmpi
1883 :
1884 220812 : shift_col = 1 + mod(me_band+iblock-1,nmpi) * cols(cprjX)
1885 :
1886 220812 : call xgBlock_setBlock(X_spinor,X_block,rows(X_spinor),cols(cprjX),fcol=shift_col)
1887 :
1888 278762 : if (iblock==1) then
1889 :
1890 57950 : call timab(tim_apply_prj_gemm,1,tsec)
1891 57950 : call xgBlock_gemm('n','n',1.0d0,projs,cprjX,1.d0,X_block)
1892 57950 : call timab(tim_apply_prj_gemm,2,tsec)
1893 :
1894 : else
1895 :
1896 162862 : call timab(tim_apply_prj_mpi,1,tsec)
1897 162862 : tag = iblock
1898 162862 : dest = mod(me_band-(iblock-1),nmpi)
1899 162862 : if (dest<0) dest=dest+nmpi
1900 162862 : call xgBlock_mpi_isend(cprjX,dest,tag,request)
1901 162862 : source = mod(me_band+(iblock-1),nmpi)
1902 162862 : call xgBlock_mpi_recv(work_mpi,source,tag)
1903 162862 : call timab(tim_apply_prj_mpi,2,tsec)
1904 :
1905 162862 : call timab(tim_apply_prj_gemm,1,tsec)
1906 162862 : call xgBlock_gemm('n','n',1.0d0,projs,work_mpi,1.d0,X_block)
1907 162862 : call timab(tim_apply_prj_gemm,2,tsec)
1908 :
1909 162862 : call timab(tim_apply_prj_mpi,1,tsec)
1910 162862 : call xmpi_wait(request,ierr)
1911 162862 : call timab(tim_apply_prj_mpi,2,tsec)
1912 :
1913 : end if
1914 :
1915 : end do
1916 :
1917 : end if
1918 :
1919 : end if
1920 :
1921 314832 : call timab(tim_apply_prj,2,tsec)
1922 :
1923 314832 : end subroutine xg_nonlop_apply_prj
1924 : !!***
1925 :
1926 142520 : subroutine xg_nonlop_apply_diag(xg_nonlop,diag_op,cprjin,cprjout)
1927 :
1928 : type(xg_nonlop_t), intent(in) :: xg_nonlop
1929 : type(xgBlock_t), intent(in) :: diag_op
1930 : type(xgBlock_t), intent(in) :: cprjin
1931 : type(xgBlock_t), intent(inout) :: cprjout
1932 :
1933 : logical :: loop_over_atoms
1934 : integer :: ia, iband, cprjdim, shift_itypat, iatom, itypat, nattyp_i, nlmn, shift
1935 : integer :: space_cprj, cplex, nlmn_max
1936 : integer :: nspinor, nrows, ncols
1937 :
1938 : type(xg_t) :: cprjin_nlmn_max,cprjout_nlmn_max
1939 : type(xgBlock_t) :: cprjin_nlmn,cprjout_nlmn,diag_op_iatom
1940 71260 : real(dp),pointer :: cprjin_nlmn_(:,:),cprjout_nlmn_(:,:)
1941 71260 : real(dp),pointer :: cprjin_(:,:),cprjout_(:,:)
1942 : real(dp) :: tsec(2)
1943 :
1944 71260 : call timab(tim_apply_diag,1,tsec)
1945 :
1946 71260 : call xgBlock_getsize(cprjin,nrows,ncols)
1947 :
1948 71260 : cprjdim = xg_nonlop%cprjdim
1949 71260 : if (nrows/=cprjdim) then
1950 0 : ABI_ERROR('nrows/=cprjdim')
1951 : end if
1952 71260 : call xgBlock_check(cprjin,cprjout)
1953 :
1954 71260 : space_cprj = space(cprjin)
1955 71260 : if (space_cprj==SPACE_C) then
1956 : cplex=2
1957 : else
1958 59308 : cplex=1
1959 : end if
1960 :
1961 71260 : nspinor=xg_nonlop%nspinor
1962 71260 : nlmn_max=xg_nonlop%nlmn_max
1963 :
1964 : ! Create work spaces for cprj of ONE atom for ALL bands
1965 71260 : call xg_init(cprjin_nlmn_max ,space_cprj,nlmn_max,ncols)
1966 71260 : call xg_init(cprjout_nlmn_max,space_cprj,nlmn_max,ncols)
1967 :
1968 71260 : call xgBlock_reverseMap(cprjin ,cprjin_ )
1969 71260 : call xgBlock_reverseMap(cprjout,cprjout_)
1970 :
1971 71260 : if (cols(diag_op) == xg_nonlop%ntypat) then
1972 : loop_over_atoms = .false.
1973 0 : else if (cols(diag_op) == xg_nonlop%natom) then
1974 : loop_over_atoms = .true.
1975 : else
1976 0 : ABI_ERROR('wrong cols for diag_op!')
1977 : end if
1978 71260 : shift = 0
1979 71260 : shift_itypat = 0
1980 213780 : do itypat=1,xg_nonlop%ntypat
1981 142520 : nlmn=xg_nonlop%nlmn_ntypat(itypat)
1982 142520 : nattyp_i=xg_nonlop%nattyp(itypat)
1983 213780 : if (nattyp_i>0) then
1984 142520 : call xg_setBlock(cprjin_nlmn_max ,cprjin_nlmn ,nlmn,ncols)
1985 142520 : call xg_setBlock(cprjout_nlmn_max,cprjout_nlmn,nlmn,ncols)
1986 142520 : call xgBlock_reverseMap(cprjin_nlmn ,cprjin_nlmn_ )
1987 142520 : call xgBlock_reverseMap(cprjout_nlmn,cprjout_nlmn_)
1988 142520 : if (.not.loop_over_atoms) then
1989 142520 : call xgBlock_setBlock(diag_op,diag_op_iatom,nlmn,1,fcol=itypat)
1990 : end if
1991 285040 : do ia=1,nattyp_i
1992 142520 : if (loop_over_atoms) then
1993 0 : iatom = ia + shift_itypat
1994 0 : call xgBlock_setBlock(diag_op,diag_op_iatom,nlmn,1,fcol=iatom)
1995 : end if
1996 : ! Copy cprj of ONE atom for ALL bands from cprjin to cprin_nlmn
1997 546560 : do iband=1,ncols
1998 32411960 : cprjin_nlmn_(1:cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,iband)
1999 : end do
2000 142520 : call xgBlock_apply_diag(cprjin_nlmn,diag_op_iatom,1,Y=cprjout_nlmn)
2001 546560 : do iband=1,ncols
2002 : cprjout_(1+shift:cplex*nlmn+shift,iband) = cprjout_(1+shift:cplex*nlmn+shift,iband) &
2003 32411960 : & + cprjout_nlmn_(1:cplex*nlmn,iband)
2004 : end do
2005 285040 : shift=shift+cplex*nlmn
2006 : end do
2007 142520 : shift_itypat = shift_itypat + nattyp_i
2008 : end if
2009 :
2010 : end do
2011 :
2012 71260 : call xg_free(cprjin_nlmn_max)
2013 71260 : call xg_free(cprjout_nlmn_max)
2014 :
2015 71260 : call timab(tim_apply_diag,2,tsec)
2016 :
2017 71260 : end subroutine xg_nonlop_apply_diag
2018 : !!***
2019 :
2020 2827252 : subroutine xg_nonlop_apply_Aij(xg_nonlop,Aij,cprjin,cprjout,A_with_spin)
2021 :
2022 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2023 : type(xgBlock_t), intent(in) :: Aij
2024 : type(xgBlock_t), intent(in) :: cprjin
2025 : type(xgBlock_t), intent(inout) :: cprjout
2026 : logical,optional,intent(in) :: A_with_spin
2027 :
2028 : logical :: loop_over_atoms
2029 : integer :: ia, iband, cprjdim, shift_itypat, iatom, itypat, nattyp_i, nlmn, shift
2030 : integer :: space_aij, space_cprj, cplex, nlmn_max
2031 : integer :: nspinor, nrows, ncols, nrows_A, ncols_A
2032 : integer :: nlmn_1atom,nlmn_max_1atom,ncols_1atom
2033 :
2034 : type(xg_t) :: cprjin_nlmn_max,cprjout_nlmn_max
2035 : type(xg_t),target :: Aij_complex
2036 : type(xgBlock_t) :: cprjin_nlmn,cprjout_nlmn
2037 : type(xgBlock_t) :: Aij_iatom,Aij_iatom_
2038 1413626 : real(dp),pointer :: cprjin_nlmn_(:,:),cprjout_nlmn_(:,:)
2039 1413626 : real(dp),pointer :: cprjin_(:,:),cprjout_(:,:)
2040 : real(dp) :: tsec(2)
2041 : logical :: aij_r2c,A_with_spin_
2042 :
2043 1413626 : call timab(tim_apply_Aij,1,tsec)
2044 :
2045 1413626 : call xgBlock_getsize(cprjin,nrows,ncols)
2046 :
2047 1413626 : cprjdim = xg_nonlop%cprjdim
2048 1413626 : if (nrows/=cprjdim) then
2049 0 : ABI_ERROR('nrows/=cprjdim')
2050 : end if
2051 1413626 : call xgBlock_check(cprjin,cprjout)
2052 :
2053 1413626 : space_cprj = space(cprjin)
2054 1413626 : if (space_cprj==SPACE_C) then
2055 : cplex=2
2056 : else
2057 522161 : cplex=1
2058 : end if
2059 1413626 : space_aij = space(Aij)
2060 1413626 : aij_r2c = .false.
2061 1413626 : if (space_cprj/=space_aij) then
2062 345425 : if (space_aij==SPACE_R.and.space_cprj==SPACE_C) then
2063 : aij_r2c = .true.
2064 : else
2065 0 : ABI_ERROR('space_aij and space_cprj are not compatible')
2066 : end if
2067 : end if
2068 :
2069 1413626 : nspinor=xg_nonlop%nspinor
2070 1413626 : nlmn_max=xg_nonlop%nlmn_max
2071 :
2072 1413626 : A_with_spin_=.true.
2073 1413626 : if (present(A_with_spin)) then
2074 708025 : A_with_spin_=A_with_spin
2075 : end if
2076 708025 : if (A_with_spin_) then
2077 705601 : nlmn_max_1atom = nlmn_max * nspinor
2078 705601 : ncols_1atom = ncols / nspinor
2079 : else
2080 708025 : nlmn_max_1atom = nlmn_max
2081 708025 : ncols_1atom = ncols
2082 : end if
2083 :
2084 1413626 : if (aij_r2c) then
2085 345425 : if (rows(Aij) /= nlmn_max) then
2086 0 : ABI_ERROR('wrong rows for Aij')
2087 : end if
2088 345425 : if (cols(Aij) == xg_nonlop%ntypat*nlmn_max) then
2089 : loop_over_atoms = .false.
2090 18421 : else if (cols(Aij) == xg_nonlop%natom*nlmn_max) then
2091 : loop_over_atoms = .true.
2092 : else
2093 0 : ABI_ERROR('wrong cols for Aij (aij_r2c)')
2094 : end if
2095 : else
2096 1068201 : if (rows(Aij) /= nlmn_max_1atom) then
2097 0 : ABI_ERROR('wrong rows for Aij')
2098 : end if
2099 1068201 : if (cols(Aij) == xg_nonlop%ntypat*nlmn_max_1atom) then
2100 : loop_over_atoms = .false.
2101 18070 : else if (cols(Aij) == xg_nonlop%natom*nlmn_max_1atom) then
2102 : loop_over_atoms = .true.
2103 : else
2104 0 : ABI_ERROR('wrong cols for Aij')
2105 : end if
2106 : end if
2107 :
2108 : ! Create work spaces for cprj of ONE atom for ALL bands
2109 1413626 : call xg_init(cprjin_nlmn_max ,space_cprj,nlmn_max_1atom,ncols_1atom)
2110 1413626 : call xg_init(cprjout_nlmn_max,space_cprj,nlmn_max_1atom,ncols_1atom)
2111 :
2112 1413626 : call xgBlock_reverseMap(cprjin ,cprjin_ )
2113 1413626 : call xgBlock_reverseMap(cprjout,cprjout_)
2114 :
2115 1413626 : shift = 0
2116 1413626 : shift_itypat = 0
2117 4231761 : do itypat=1,xg_nonlop%ntypat
2118 2818135 : nlmn=xg_nonlop%nlmn_ntypat(itypat)
2119 2818135 : if (A_with_spin_) then
2120 1377521 : nlmn_1atom = nlmn*nspinor
2121 : else
2122 1440614 : nlmn_1atom = nlmn
2123 : end if
2124 2818135 : nattyp_i=xg_nonlop%nattyp(itypat)
2125 4231761 : if (nattyp_i>0) then
2126 2768036 : call xg_setBlock(cprjin_nlmn_max ,cprjin_nlmn ,nlmn_1atom,ncols_1atom)
2127 2768036 : call xg_setBlock(cprjout_nlmn_max,cprjout_nlmn,nlmn_1atom,ncols_1atom)
2128 2768036 : call xgBlock_reverseMap(cprjin_nlmn ,cprjin_nlmn_ )
2129 2768036 : call xgBlock_reverseMap(cprjout_nlmn,cprjout_nlmn_)
2130 2768036 : if (aij_r2c) call xg_init(Aij_complex,SPACE_C,nlmn_1atom,nlmn_1atom)
2131 2768036 : if (.not.loop_over_atoms) then
2132 2718988 : if (aij_r2c) then
2133 627647 : call xgBlock_setBlock(Aij,Aij_iatom,nlmn,nlmn,fcol=1+(itypat-1)*nlmn_max)
2134 : else
2135 2091341 : call xgBlock_setBlock(Aij,Aij_iatom,nlmn_1atom,nlmn_1atom,fcol=1+(itypat-1)*nlmn_max_1atom)
2136 : end if
2137 : end if
2138 5609800 : do ia=1,nattyp_i
2139 2841764 : if (loop_over_atoms) then
2140 73894 : iatom = ia + shift_itypat
2141 73894 : if (aij_r2c) then
2142 37754 : call xgBlock_setBlock(Aij,Aij_iatom,nlmn,nlmn,fcol=1+(iatom-1)*nlmn_max)
2143 : else
2144 36140 : call xgBlock_setBlock(Aij,Aij_iatom,nlmn_1atom,nlmn_1atom,fcol=1+(iatom-1)*nlmn_max_1atom)
2145 : end if
2146 : end if
2147 2841764 : call xgBlock_getsize(Aij_iatom,nrows_A,ncols_A)
2148 2841764 : if (.not.aij_r2c) then
2149 2149602 : if (nrows_A/=nlmn_1atom) then
2150 0 : ABI_ERROR('nrows_A/=nlmn_1atom')
2151 : end if
2152 2149602 : if (ncols_A/=nlmn_1atom) then
2153 0 : ABI_ERROR('ncols_A/=nlmn_1atom')
2154 : end if
2155 : else
2156 692162 : if (nrows_A/=nlmn) then
2157 0 : ABI_ERROR('nrows_A/=nlmn')
2158 : end if
2159 692162 : if (ncols_A/=nlmn) then
2160 0 : ABI_ERROR('ncols_A/=nlmn')
2161 : end if
2162 : end if
2163 : ! if needed, transfer real matrix to a complex one
2164 2841764 : if (aij_r2c) then
2165 692162 : call xgBlock_r2c(Aij_iatom,Aij_complex%self,nspinor)
2166 692162 : Aij_iatom_ = Aij_complex%self
2167 : else
2168 2149602 : Aij_iatom_ = Aij_iatom
2169 : end if
2170 : ! Copy cprj of ONE atom for ALL bands from cprjin to cprin_nlmn
2171 2841764 : if (A_with_spin_) then
2172 5332134 : do iband=1,ncols_1atom
2173 121269702 : cprjin_nlmn_(1:cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,1+nspinor*(iband-1))
2174 : end do
2175 1412514 : if (nspinor==2) then
2176 1367358 : do iband=1,ncols_1atom
2177 39094014 : cprjin_nlmn_(1+cplex*nlmn:2*cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,nspinor*iband)
2178 : end do
2179 : end if
2180 : else
2181 12099738 : do iband=1,ncols_1atom
2182 330920090 : cprjin_nlmn_(1:cplex*nlmn,iband) = cprjin_(1+shift:cplex*nlmn+shift,iband)
2183 : end do
2184 : end if
2185 :
2186 2841764 : call xgBlock_gemm('n','n',1.0d0,Aij_iatom_,cprjin_nlmn,0.d0,cprjout_nlmn,timing=.false.)
2187 :
2188 2841764 : if (A_with_spin_) then
2189 5332134 : do iband=1,ncols_1atom
2190 : cprjout_(1+shift:cplex*nlmn+shift,1+nspinor*(iband-1)) = cprjout_(1+shift:cplex*nlmn+shift,1+nspinor*(iband-1)) &
2191 121269702 : & + cprjout_nlmn_(1:cplex*nlmn,iband)
2192 : end do
2193 1412514 : if (nspinor==2) then
2194 1367358 : do iband=1,ncols_1atom
2195 : cprjout_(1+shift:cplex*nlmn+shift,nspinor*iband) = cprjout_(1+shift:cplex*nlmn+shift,nspinor*iband) &
2196 39094014 : & + cprjout_nlmn_(1+cplex*nlmn:2*cplex*nlmn,iband)
2197 : end do
2198 : end if
2199 : else
2200 12099738 : do iband=1,ncols_1atom
2201 : cprjout_(1+shift:cplex*nlmn+shift,iband) = cprjout_(1+shift:cplex*nlmn+shift,iband) &
2202 330920090 : & + cprjout_nlmn_(1:cplex*nlmn,iband)
2203 : end do
2204 : end if
2205 8451564 : shift=shift+cplex*nlmn
2206 : end do
2207 :
2208 2768036 : if (aij_r2c) call xg_free(Aij_complex)
2209 2768036 : shift_itypat = shift_itypat + nattyp_i
2210 : end if
2211 :
2212 : end do
2213 :
2214 1413626 : call xg_free(cprjin_nlmn_max)
2215 1413626 : call xg_free(cprjout_nlmn_max)
2216 :
2217 1413626 : call timab(tim_apply_Aij,2,tsec)
2218 :
2219 1413626 : end subroutine xg_nonlop_apply_Aij
2220 : !!***
2221 :
2222 189900 : subroutine xg_nonlop_precond_iterative_refinement(xg_nonlop,A,precond,cprj_in,cprj_out,cprj_work)
2223 :
2224 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2225 : type(xgBlock_t), intent(in ) :: A,precond
2226 : type(xgBlock_t), intent(in ) :: cprj_in
2227 : type(xgBlock_t), intent(inout) :: cprj_out,cprj_work
2228 :
2229 : integer :: iter,cprjdim,ncols,additional_steps_to_take
2230 : !integer :: rows_A
2231 : real(dp), parameter :: tolerance = 1e-14 ! maximum relative error. TODO: use tolwfr ?
2232 : type(xg_t) :: err
2233 : !real(dp) :: cond
2234 : real(dp) :: norm,max_err,previous_max_err,convergence_rate,tsec(2)
2235 :
2236 94950 : call timab(tim_iter_refinement,1,tsec)
2237 :
2238 : ! Note that precond is block-diagonal whereas A is not
2239 :
2240 94950 : cprjdim = xg_nonlop%cprjdim
2241 94950 : ncols = cols(cprj_in)
2242 94950 : if (cprjdim/=rows(cprj_in)) then
2243 0 : ABI_ERROR('Wrong size for cprj_in')
2244 : end if
2245 94950 : call xgBlock_check(cprj_in,cprj_out)
2246 94950 : call xgBlock_check(cprj_in,cprj_work)
2247 94950 : if (rows(A)/=cprjdim.or.cols(A)/=cprjdim) then
2248 0 : ABI_ERROR('Wrong size for A')
2249 : end if
2250 :
2251 94950 : call xg_init(err,SPACE_R,ncols,1,xmpi_comm_self)
2252 :
2253 94950 : call xgBlock_colwiseNorm2(cprj_in,err%self,max_val=norm)
2254 :
2255 : ! Y_0 = PX (with P block diagonal and "close" to A^-1)
2256 94950 : call xgBlock_zero(cprj_out)
2257 94950 : call xg_nonlop_apply_Aij(xg_nonlop,precond,cprj_in,cprj_out,A_with_spin=.false.)
2258 :
2259 94950 : additional_steps_to_take = -1
2260 708025 : do iter=1,30
2261 : ! compute AY_i
2262 708025 : call xgBlock_gemm('n','n',1.0d0,A,cprj_out,0.0d0,cprj_work)
2263 : ! ITEST
2264 : !write(903,*) 'Apply getBm1X to spd matrix of size', rows(A), cols(A)
2265 : !rows_A = rows(A)
2266 : !call xgBlock_hermitian_pd_cond(A, rows_A, cond)
2267 : !write(903,*) 'cond(B)=', cond
2268 : !flush(903)
2269 : ! ITEST
2270 : ! RES = AY_i - X
2271 708025 : call xgBlock_saxpy(cprj_work,-1.0d0,cprj_in)
2272 708025 : call xgBlock_colwiseNorm2(cprj_work,err%self,max_val=max_err)
2273 708025 : max_err = sqrt(max_err / norm)
2274 708025 : if(max_err < tolerance .or. additional_steps_to_take == 1) then
2275 : exit
2276 : ! We might stall and never get to the specified precision because of machine errors.
2277 : ! If we got to 1e-10, extrapolate convergence rate and determine the number of additional
2278 : ! steps to take to reach precision
2279 613085 : else if(max_err < 1e-10 .and. additional_steps_to_take == -1) then
2280 94950 : convergence_rate = -LOG(1e-10) / iter
2281 94950 : additional_steps_to_take = CEILING(-LOG(tolerance/1e-10)/convergence_rate) + 1
2282 518135 : else if(additional_steps_to_take > 0) then
2283 94555 : if(previous_max_err<max_err)exit
2284 94545 : additional_steps_to_take = additional_steps_to_take - 1
2285 : end if
2286 613075 : previous_max_err=max_err
2287 : ! RES = X - AY_i
2288 613075 : call xgBlock_scale(cprj_work,-1.0d0,1)
2289 : ! Y_(i+1) = Y_i + P RES
2290 1416050 : call xg_nonlop_apply_Aij(xg_nonlop,precond,cprj_work,cprj_out,A_with_spin=.false.)
2291 : end do
2292 :
2293 94950 : call xg_free(err)
2294 :
2295 94950 : call timab(tim_iter_refinement,2,tsec)
2296 :
2297 94950 : end subroutine xg_nonlop_precond_iterative_refinement
2298 : !!***
2299 :
2300 442258 : subroutine xg_nonlop_mult_cprj(xg_nonlop,cprj_left,cprj_right,res,blocksize)
2301 :
2302 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2303 : type(xgBlock_t), intent(in) :: cprj_left,cprj_right
2304 : type(xgBlock_t), intent(inout) :: res
2305 : integer, intent(in),optional :: blocksize
2306 :
2307 : integer :: space_res
2308 : integer :: blocksize_,blocksize_spinor,iblock_mpi,nblocks_mpi,shift_row,shift_col,shift_col_mpi
2309 : integer :: iblock_left,iblock_right,nblocks_left,nblocks_right
2310 : integer :: res_nrows,res_ncols,cprjdim
2311 : integer :: nrows_r,nrows_l,ncols_r,ncols_l,nspinor
2312 : integer :: comm_cprj,tag,request,ierr,me_band,source,dest
2313 : logical :: multiblock
2314 : real(dp) :: tsec(2)
2315 : type(xg_t) :: res_work_mpi,res_block,res_block_mpi,cprj_work_mpi
2316 : type(xgBlock_t) :: cprj_left_spinor,cprj_right_spinor
2317 :
2318 442258 : call timab(tim_mult_cprj,1,tsec)
2319 :
2320 442258 : comm_cprj = comm(cprj_right)
2321 442258 : nblocks_mpi = xmpi_comm_size(comm_cprj)
2322 :
2323 442258 : cprjdim = xg_nonlop%cprjdim
2324 442258 : nspinor = xg_nonlop%nspinor
2325 :
2326 442258 : call xgBlock_reshape_spinor(cprj_right,cprj_right_spinor,nspinor,COLS2ROWS)
2327 442258 : call xgBlock_reshape_spinor(cprj_left ,cprj_left_spinor ,nspinor,COLS2ROWS)
2328 :
2329 442258 : nrows_r = rows(cprj_right_spinor)
2330 442258 : nrows_l = rows(cprj_left_spinor)
2331 :
2332 442258 : ncols_r = cols(cprj_right_spinor)
2333 442258 : ncols_l = cols(cprj_left_spinor)
2334 :
2335 442258 : me_band = xg_nonlop%me_band
2336 :
2337 442258 : if (nrows_r/=nspinor*cprjdim) then
2338 0 : ABI_ERROR("rows(cprj_right)/=nspinor*cprjdim")
2339 : end if
2340 442258 : if (nrows_l/=nspinor*cprjdim) then
2341 0 : ABI_ERROR("rows(cprj_left)/=nspinor*cprjdim")
2342 : end if
2343 442258 : if (rows(res)/=nblocks_mpi*ncols_l) then
2344 0 : ABI_ERROR("rows(res)/=nblocks_mpi*cols(cprj_left)")
2345 : end if
2346 442258 : if (cols(res)/=nblocks_mpi*ncols_r) then
2347 0 : ABI_ERROR("cols(res)/=nblocks_mpi*cols(cprj_right)")
2348 : end if
2349 :
2350 442258 : blocksize_ = ncols_r
2351 442258 : if (present(blocksize)) then
2352 442258 : if (mod(blocksize,nspinor)/=0) then
2353 0 : ABI_ERROR("wrong blocksize (nspinor)")
2354 : end if
2355 442258 : if (mod(ncols_l,blocksize / nspinor)/=0) then
2356 0 : ABI_ERROR("wrong blocksize")
2357 : end if
2358 : blocksize_ = blocksize
2359 : end if
2360 :
2361 442258 : if (nblocks_mpi==1) then
2362 :
2363 159474 : call timab(tim_mult_cprj_gemm,1,tsec)
2364 159474 : call xgBlock_gemm('t','n',1.0d0,cprj_left_spinor,cprj_right_spinor,1.d0,res)
2365 159474 : call timab(tim_mult_cprj_gemm,2,tsec)
2366 :
2367 : else
2368 :
2369 282784 : blocksize_spinor = blocksize_ / nspinor
2370 282784 : nblocks_right = ncols_r / blocksize_spinor
2371 282784 : nblocks_left = ncols_l / blocksize_spinor
2372 :
2373 282784 : multiblock = .false.
2374 282784 : if (nblocks_right>1.or.nblocks_left>1) then
2375 164454 : multiblock = .true.
2376 : end if
2377 :
2378 282784 : res_nrows = rows(res)
2379 282784 : res_ncols = cols(res)
2380 :
2381 282784 : space_res = space(cprj_right)
2382 :
2383 282784 : call xg_init(res_block_mpi,space_res,ncols_l,ncols_r,xmpi_comm_null)
2384 282784 : if (multiblock) then
2385 164454 : call xg_init(res_block,space_res,blocksize_spinor,blocksize_spinor,xmpi_comm_null)
2386 : end if
2387 282784 : call xg_init(res_work_mpi,space_res,res_nrows,res_ncols,xmpi_comm_null)
2388 282784 : call xgBlock_zero(res_work_mpi%self)
2389 :
2390 282784 : call xg_init(cprj_work_mpi,space_res,nspinor*cprjdim,ncols_r,comm_cprj)
2391 :
2392 1353528 : do iblock_mpi=1,nblocks_mpi
2393 :
2394 1070744 : if (iblock_mpi==1) then
2395 :
2396 282784 : call timab(tim_mult_cprj_gemm,1,tsec)
2397 282784 : call xgBlock_gemm('t','n',1.0d0,cprj_left_spinor,cprj_right_spinor,0.d0,res_block_mpi%self)
2398 282784 : call timab(tim_mult_cprj_gemm,2,tsec)
2399 :
2400 : else
2401 :
2402 787960 : call timab(tim_mult_cprj_mpi,1,tsec)
2403 787960 : tag = iblock_mpi
2404 787960 : dest = mod(me_band-(iblock_mpi-1),nblocks_mpi)
2405 787960 : if (dest<0) dest=dest+nblocks_mpi
2406 787960 : call xgBlock_mpi_isend(cprj_right_spinor,dest,tag,request)
2407 787960 : source = mod(me_band+(iblock_mpi-1),nblocks_mpi)
2408 787960 : call xgBlock_mpi_recv(cprj_work_mpi%self,source,tag)
2409 787960 : call timab(tim_mult_cprj_mpi,2,tsec)
2410 :
2411 787960 : call timab(tim_mult_cprj_gemm,1,tsec)
2412 787960 : call xgBlock_gemm('t','n',1.0d0,cprj_left_spinor,cprj_work_mpi%self,0.d0,res_block_mpi%self)
2413 787960 : call timab(tim_mult_cprj_gemm,2,tsec)
2414 :
2415 : end if
2416 :
2417 1070744 : if (.not.multiblock) then
2418 447764 : shift_row = me_band*ncols_l
2419 447764 : shift_col = mod(me_band+iblock_mpi-1,res_ncols)*ncols_r
2420 447764 : if (shift_col>=res_ncols) shift_col = shift_col - res_ncols
2421 :
2422 447764 : call timab(tim_mult_cprj_copy,1,tsec)
2423 447764 : call xgBlock_partialcopy(res_block_mpi%self,res_work_mpi%self,shift_row,shift_col,SMALL2BIG)
2424 447764 : call timab(tim_mult_cprj_copy,2,tsec)
2425 :
2426 : else
2427 1458812 : do iblock_right=1,nblocks_right
2428 3689348 : do iblock_left=1,nblocks_left
2429 2230536 : shift_row = (iblock_left-1)*blocksize_spinor
2430 2230536 : shift_col = (iblock_right-1)*blocksize_spinor
2431 :
2432 2230536 : call timab(tim_mult_cprj_copy,1,tsec)
2433 2230536 : call xgBlock_partialcopy(res_block_mpi%self,res_block%self,shift_row,shift_col,BIG2SMALL)
2434 2230536 : call timab(tim_mult_cprj_copy,2,tsec)
2435 :
2436 2230536 : shift_row = (me_band*blocksize_spinor) + (iblock_left-1)*res_nrows/nblocks_left
2437 2230536 : shift_col_mpi = mod(me_band+iblock_mpi-1,res_ncols/nblocks_right)*blocksize_spinor
2438 2230536 : if (shift_col_mpi>=res_ncols/nblocks_right) shift_col_mpi = shift_col_mpi - res_ncols/nblocks_right
2439 2230536 : shift_col = shift_col_mpi + (iblock_right-1)*res_ncols/nblocks_right
2440 :
2441 2230536 : call timab(tim_mult_cprj_copy,1,tsec)
2442 2230536 : call xgBlock_partialcopy(res_block%self,res_work_mpi%self,shift_row,shift_col,SMALL2BIG)
2443 3066368 : call timab(tim_mult_cprj_copy,2,tsec)
2444 :
2445 : end do
2446 : end do
2447 : end if
2448 :
2449 1353528 : if (iblock_mpi>1) then
2450 787960 : call timab(tim_mult_cprj_mpi,1,tsec)
2451 787960 : call xmpi_wait(request,ierr)
2452 787960 : call timab(tim_mult_cprj_mpi,2,tsec)
2453 : end if
2454 :
2455 : end do
2456 :
2457 282784 : call timab(tim_mult_cprj_mpi,1,tsec)
2458 282784 : call xgBlock_mpi_sum(res_work_mpi%self,comm=comm_cprj)
2459 282784 : call timab(tim_mult_cprj_mpi,2,tsec)
2460 :
2461 282784 : call xgBlock_add(res,res_work_mpi%self)
2462 :
2463 282784 : if (multiblock) then
2464 164454 : call xg_free(res_block)
2465 : end if
2466 282784 : call xg_free(res_block_mpi)
2467 282784 : call xg_free(res_work_mpi)
2468 282784 : call xg_free(cprj_work_mpi)
2469 :
2470 : end if
2471 :
2472 442258 : call timab(tim_mult_cprj,2,tsec)
2473 :
2474 442258 : end subroutine xg_nonlop_mult_cprj
2475 : !!***
2476 :
2477 12920 : subroutine xg_nonlop_colwiseXAX(xg_nonlop,Aij,cprj,cprj_work,res)
2478 :
2479 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2480 : type(xgBlock_t), intent(in) :: cprj,Aij
2481 : type(xgBlock_t), intent(inout) :: cprj_work,res
2482 :
2483 : integer :: ncols
2484 : type(xgBlock_t) :: cprj_spinor,cprj_work_spinor
2485 :
2486 12920 : call xgBlock_check(cprj,cprj_work)
2487 12920 : ncols = cols(cprj)
2488 12920 : if (ncols/=xg_nonlop%nspinor*rows(res)) then
2489 0 : ABI_ERROR('Wrong cols for cprj or res.')
2490 : end if
2491 :
2492 12920 : call xgBlock_zero(cprj_work)
2493 12920 : call xg_nonlop_apply_Aij(xg_nonlop,Aij,cprj,cprj_work)
2494 :
2495 12920 : call xgBlock_reshape_spinor(cprj ,cprj_spinor ,xg_nonlop%nspinor,COLS2ROWS)
2496 12920 : call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,xg_nonlop%nspinor,COLS2ROWS)
2497 12920 : call xgBlock_colwiseDotProduct(cprj_spinor,cprj_work_spinor,res,comm_loc=xmpi_comm_null)
2498 :
2499 12920 : end subroutine xg_nonlop_colwiseXAX
2500 : !!***
2501 :
2502 3264 : subroutine xg_nonlop_colwiseXDX(xg_nonlop,diag,cprj,cprj_work,res)
2503 :
2504 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2505 : type(xgBlock_t), intent(in) :: cprj,diag
2506 : type(xgBlock_t), intent(inout) :: cprj_work,res
2507 :
2508 : integer :: ncols,space_diag,space_res
2509 : type(xgBlock_t) :: cprj_spinor,cprj_work_spinor
2510 : type(xg_t) :: res_complex
2511 :
2512 3264 : call xgBlock_check(cprj,cprj_work)
2513 3264 : ncols = cols(cprj)
2514 3264 : if (ncols/=xg_nonlop%nspinor*rows(res)) then
2515 0 : ABI_ERROR('Wrong cols for cprj or res.')
2516 : end if
2517 3264 : space_diag = space(diag)
2518 3264 : space_res = space(res)
2519 3264 : if (space_diag==SPACE_C) then
2520 0 : if (space_res/=SPACE_C) then
2521 0 : ABI_ERROR('space(res) should be SPACE_C.')
2522 : end if
2523 3264 : else if (space_diag/=SPACE_R) then
2524 0 : ABI_ERROR('space(diag) should be SPACE_C or SPACE_R.')
2525 : end if
2526 :
2527 3264 : call xgBlock_zero(cprj_work)
2528 3264 : call xg_nonlop_apply_diag(xg_nonlop,diag,cprj,cprj_work)
2529 :
2530 3264 : call xgBlock_reshape_spinor(cprj ,cprj_spinor ,xg_nonlop%nspinor,COLS2ROWS)
2531 3264 : call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,xg_nonlop%nspinor,COLS2ROWS)
2532 :
2533 : ! If space_diag==SPACE_R, the result is actually real and can be stored in a xgBlock with SPACE_R
2534 3264 : if ( space_diag==SPACE_R .and. space_res==SPACE_R .and. space(cprj)==SPACE_C) then
2535 544 : call xg_init(res_complex,SPACE_C,rows(res),cols(res))
2536 544 : call xgBlock_colwiseDotProduct(cprj_spinor,cprj_work_spinor,res_complex%self,comm_loc=xmpi_comm_null)
2537 544 : call xgBlock_c2r(res_complex%self,res)
2538 544 : call xg_free(res_complex)
2539 : else
2540 2720 : call xgBlock_colwiseDotProduct(cprj_spinor,cprj_work_spinor,res,comm_loc=xmpi_comm_null)
2541 : end if
2542 :
2543 3264 : end subroutine xg_nonlop_colwiseXDX
2544 : !!***
2545 :
2546 3264 : subroutine xg_nonlop_colwiseXHX(xg_nonlop,cprj,cprj_work,res)
2547 :
2548 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2549 : type(xgBlock_t), intent(in) :: cprj
2550 : type(xgBlock_t), intent(inout) :: cprj_work,res
2551 :
2552 : integer :: nmpi,ncols,nres,shift
2553 : ! type(xg_t) :: res_mpi
2554 : type(xgBlock_t) :: res_mpi,res_tmp
2555 :
2556 3264 : if (cols(res)/=1) then
2557 0 : ABI_ERROR('cols(res)/=1')
2558 : end if
2559 3264 : nmpi = xmpi_comm_size(comm(cprj))
2560 3264 : ncols = cols(cprj)
2561 3264 : nres = rows(res)
2562 3264 : if (nres*xg_nonlop%nspinor/=nmpi*ncols) then
2563 0 : ABI_ERROR('rows(res)*nspinor/=nmpi*cols(cprj))')
2564 : end if
2565 :
2566 3264 : call xgBlock_zero(res)
2567 :
2568 3264 : if (nmpi==1) then
2569 1088 : res_mpi = res
2570 : else
2571 2176 : call xgBlock_setBlock(res,res_tmp,nres,1)
2572 2176 : call xgBlock_reshape(res_tmp,1,nres)
2573 2176 : shift = xg_nonlop%me_band*ncols
2574 2176 : call xgBlock_setBlock(res_tmp,res_mpi,1,ncols,fcol=1+shift)
2575 2176 : call xgBlock_reshape(res_mpi,ncols,1)
2576 : end if
2577 :
2578 3264 : if (xg_nonlop%paw) then
2579 0 : call xg_nonlop_colwiseXAX(xg_nonlop,xg_nonlop%Dij_spin,cprj,cprj_work,res_mpi)
2580 : else
2581 3264 : call xg_nonlop_colwiseXDX(xg_nonlop,xg_nonlop%ekb%self,cprj,cprj_work,res_mpi)
2582 : end if
2583 :
2584 3264 : call xgBlock_mpi_sum(res,comm=xg_nonlop%comm_band)
2585 :
2586 3264 : end subroutine xg_nonlop_colwiseXHX
2587 : !!***
2588 :
2589 410705 : subroutine xg_nonlop_getXAY(xg_nonlop,Aij,cprj_left,cprj_right,cprj_work,res,blocksize)
2590 :
2591 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2592 : type(xgBlock_t), intent(in) :: cprj_left,cprj_right,Aij
2593 : type(xgBlock_t), intent(inout) :: cprj_work,res
2594 : integer,intent(in),optional :: blocksize
2595 :
2596 : integer :: blocksize_
2597 :
2598 410705 : call xgBlock_zero(cprj_work)
2599 410705 : call xg_nonlop_apply_Aij(xg_nonlop,Aij,cprj_right,cprj_work)
2600 :
2601 410705 : blocksize_ = cols(cprj_right)
2602 410705 : if (present(blocksize)) then
2603 410705 : blocksize_ = blocksize
2604 : end if
2605 410705 : call xg_nonlop_mult_cprj(xg_nonlop,cprj_left,cprj_work,res,blocksize=blocksize_)
2606 :
2607 410705 : end subroutine xg_nonlop_getXAY
2608 : !!***
2609 :
2610 31553 : subroutine xg_nonlop_getXDY(xg_nonlop,diag,cprj_left,cprj_right,cprj_work,res,blocksize)
2611 :
2612 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2613 : type(xgBlock_t), intent(in) :: cprj_left,cprj_right,diag
2614 : type(xgBlock_t), intent(inout) :: cprj_work,res
2615 : integer,intent(in),optional :: blocksize
2616 :
2617 : integer :: blocksize_
2618 :
2619 31553 : call xgBlock_zero(cprj_work)
2620 31553 : call xg_nonlop_apply_diag(xg_nonlop,diag,cprj_right,cprj_work)
2621 :
2622 31553 : blocksize_ = cols(cprj_right)
2623 31553 : if (present(blocksize)) then
2624 31553 : blocksize_ = blocksize
2625 : end if
2626 31553 : call xg_nonlop_mult_cprj(xg_nonlop,cprj_left,cprj_work,res,blocksize=blocksize_)
2627 :
2628 31553 : end subroutine xg_nonlop_getXDY
2629 : !!***
2630 :
2631 255088 : subroutine xg_nonlop_getXSY(xg_nonlop,cprj_left,cprj_right,cprj_work,res,blocksize)
2632 :
2633 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2634 : type(xgBlock_t), intent(inout) :: cprj_left,cprj_right,cprj_work,res
2635 : integer,intent(in),optional :: blocksize
2636 :
2637 : integer :: blocksize_
2638 :
2639 : real(dp) :: tsec(2)
2640 :
2641 255088 : call timab(tim_getXSY,1,tsec)
2642 :
2643 255088 : if (.not.xg_nonlop%paw) then
2644 0 : ABI_ERROR('Not implemented with paw=False.')
2645 : end if
2646 :
2647 255088 : blocksize_ = cols(cprj_right)
2648 255088 : if (present(blocksize)) then
2649 217434 : blocksize_ = blocksize
2650 : end if
2651 255088 : call xg_nonlop_getXAY(xg_nonlop,xg_nonlop%Sij%self,cprj_left,cprj_right,cprj_work,res,blocksize=blocksize_)
2652 :
2653 255088 : call timab(tim_getXSY,2,tsec)
2654 :
2655 255088 : end subroutine xg_nonlop_getXSY
2656 : !!***
2657 :
2658 187170 : subroutine xg_nonlop_getXHY(xg_nonlop,cprj_left,cprj_right,cprj_work,res,blocksize)
2659 :
2660 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2661 : type(xgBlock_t), intent(inout) :: cprj_left,cprj_right,cprj_work,res
2662 : integer,intent(in),optional :: blocksize
2663 :
2664 : integer :: blocksize_
2665 :
2666 : real(dp) :: tsec(2)
2667 :
2668 187170 : call timab(tim_getXHY,1,tsec)
2669 :
2670 187170 : blocksize_ = cols(cprj_right)
2671 187170 : if (present(blocksize)) then
2672 187170 : blocksize_ = blocksize
2673 : end if
2674 187170 : if (xg_nonlop%paw) then
2675 155617 : call xg_nonlop_getXAY(xg_nonlop,xg_nonlop%Dij_spin,cprj_left,cprj_right,cprj_work,res,blocksize=blocksize_)
2676 : else
2677 31553 : call xg_nonlop_getXDY(xg_nonlop,xg_nonlop%ekb%self,cprj_left,cprj_right,cprj_work,res,blocksize=blocksize_)
2678 : end if
2679 :
2680 187170 : call timab(tim_getXHY,2,tsec)
2681 :
2682 187170 : end subroutine xg_nonlop_getXHY
2683 : !!***
2684 :
2685 330546 : subroutine xg_nonlop_getAX(xg_nonlop,Aij,Xin,cprjin,cprj_work,work_mpi,Xout)
2686 :
2687 : use iso_c_binding
2688 :
2689 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2690 : type(xgBlock_t), intent(in) :: cprjin,Aij
2691 : type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
2692 : type(xgBlock_t), optional, intent(inout) :: Xout
2693 :
2694 : integer :: nblocks,nspinor
2695 : integer :: nrows,nrows_cprj
2696 : integer :: ncols,ncols_cprj
2697 :
2698 110182 : nblocks = xmpi_comm_size(comm(cprjin))
2699 :
2700 110182 : nspinor = xg_nonlop%nspinor
2701 :
2702 : ! check sizes
2703 110182 : if (present(Xout)) then
2704 0 : call xgBlock_check(Xin,Xout)
2705 : end if
2706 110182 : call xgBlock_check(cprjin,cprj_work)
2707 110182 : call xgBlock_getsize(Xin,nrows,ncols)
2708 110182 : call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
2709 :
2710 : ! cprj_work = sum_j Saij cprjin
2711 110182 : call xgBlock_zero(cprj_work)
2712 110182 : call xg_nonlop_apply_Aij(xg_nonlop,Aij,cprjin,cprj_work)
2713 :
2714 : ! Xout = Xin + sum_ai pai cprj_work
2715 110182 : if (present(Xout)) then
2716 0 : call xgBlock_copy(Xin,Xout)
2717 0 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xout,work_mpi)
2718 : else ! in place version
2719 110182 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xin,work_mpi)
2720 : end if
2721 :
2722 110182 : end subroutine xg_nonlop_getAX
2723 :
2724 103665 : subroutine xg_nonlop_getDX(xg_nonlop,diag,Xin,cprjin,cprj_work,work_mpi,Xout)
2725 :
2726 : use iso_c_binding
2727 :
2728 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2729 : type(xgBlock_t), intent(in) :: cprjin,diag
2730 : type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
2731 : type(xgBlock_t), optional, intent(inout) :: Xout
2732 :
2733 : integer :: nblocks,nspinor
2734 : integer :: nrows,nrows_cprj
2735 : integer :: ncols,ncols_cprj
2736 :
2737 34555 : nblocks = xmpi_comm_size(comm(cprjin))
2738 :
2739 34555 : nspinor = xg_nonlop%nspinor
2740 :
2741 : ! check sizes
2742 34555 : if (present(Xout)) then
2743 0 : call xgBlock_check(Xin,Xout)
2744 : end if
2745 34555 : call xgBlock_check(cprjin,cprj_work)
2746 34555 : call xgBlock_getsize(Xin,nrows,ncols)
2747 34555 : call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
2748 :
2749 : ! cprj_work = sum_j Saij cprjin
2750 34555 : call xgBlock_zero(cprj_work)
2751 34555 : call xg_nonlop_apply_diag(xg_nonlop,diag,cprjin,cprj_work)
2752 :
2753 : ! Xout = Xin + sum_ai pai cprj_work
2754 34555 : if (present(Xout)) then
2755 0 : call xgBlock_copy(Xin,Xout)
2756 0 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xout,work_mpi)
2757 : else ! in place version
2758 34555 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xin,work_mpi)
2759 : end if
2760 :
2761 34555 : end subroutine xg_nonlop_getDX
2762 :
2763 142425 : subroutine xg_nonlop_getHX(xg_nonlop,Xin,cprjin,cprj_work,work_mpi,Xout)
2764 :
2765 : use iso_c_binding
2766 :
2767 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2768 : type(xgBlock_t), intent(in) :: cprjin
2769 : type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
2770 : type(xgBlock_t), optional, intent(inout) :: Xout
2771 :
2772 142425 : if (present(Xout)) then
2773 0 : if (xg_nonlop%paw) then
2774 0 : call xg_nonlop_getAX(xg_nonlop,xg_nonlop%Dij_spin,Xin,cprjin,cprj_work,work_mpi,Xout=Xout)
2775 : else
2776 0 : call xg_nonlop_getDX(xg_nonlop,xg_nonlop%ekb%self,Xin,cprjin,cprj_work,work_mpi,Xout=Xout)
2777 : end if
2778 : else
2779 142425 : if (xg_nonlop%paw) then
2780 107870 : call xg_nonlop_getAX(xg_nonlop,xg_nonlop%Dij_spin,Xin,cprjin,cprj_work,work_mpi)
2781 : else
2782 34555 : call xg_nonlop_getDX(xg_nonlop,xg_nonlop%ekb%self,Xin,cprjin,cprj_work,work_mpi)
2783 : end if
2784 : end if
2785 :
2786 142425 : end subroutine xg_nonlop_getHX
2787 :
2788 2312 : subroutine xg_nonlop_getSX(xg_nonlop,Xin,cprjin,cprj_work,work_mpi,Xout)
2789 :
2790 : use iso_c_binding
2791 :
2792 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2793 : type(xgBlock_t), intent(in) :: cprjin
2794 : type(xgBlock_t), intent(inout) :: Xin,cprj_work,work_mpi
2795 : type(xgBlock_t), optional, intent(inout) :: Xout
2796 :
2797 2312 : if (.not.xg_nonlop%paw) then
2798 0 : ABI_ERROR('Not implemented with paw=False.')
2799 : end if
2800 :
2801 2312 : call xg_nonlop_getAX(xg_nonlop,xg_nonlop%Sij%self,Xin,cprjin,cprj_work,work_mpi,Xout)
2802 :
2803 2312 : end subroutine xg_nonlop_getSX
2804 :
2805 284850 : subroutine xg_nonlop_getSm1X(xg_nonlop,Xin,cprjin,cprj_work1,cprj_work2,work_mpi,Xout)
2806 :
2807 : use iso_c_binding
2808 :
2809 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2810 : type(xgBlock_t), intent(in) :: cprjin
2811 : type(xgBlock_t), intent(inout) :: Xin,cprj_work1,cprj_work2,work_mpi
2812 : type(xgBlock_t), optional, intent(inout) :: Xout
2813 :
2814 : integer :: nblocks,nspinor
2815 : integer :: nrows,nrows_cprj
2816 : integer :: ncols,ncols_cprj
2817 :
2818 94950 : if (.not.xg_nonlop%paw) then
2819 0 : ABI_ERROR('Not implemented with paw=False.')
2820 : end if
2821 :
2822 94950 : nblocks = xmpi_comm_size(comm(cprjin))
2823 :
2824 94950 : nspinor = xg_nonlop%nspinor
2825 :
2826 94950 : if (present(Xout)) then
2827 0 : call xgBlock_check(Xin,Xout)
2828 : end if
2829 94950 : call xgBlock_check(cprjin,cprj_work1)
2830 94950 : call xgBlock_check(cprjin,cprj_work2)
2831 94950 : call xgBlock_getsize(Xin,nrows,ncols)
2832 94950 : call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
2833 94950 : if (.not.associated(xg_nonlop%invSij_approx_k)) then
2834 0 : ABI_ERROR('invSij_approx not associated')
2835 : end if
2836 94950 : if (.not.associated(xg_nonlop%gram_proj_k)) then
2837 0 : ABI_ERROR('gram_proj_k should be associated')
2838 : end if
2839 :
2840 : call xg_nonlop_precond_iterative_refinement(xg_nonlop,xg_nonlop%gram_proj_k%self,xg_nonlop%invSij_approx_k%self,&
2841 94950 : & cprjin,cprj_work1,cprj_work2)
2842 94950 : call xgBlock_scale(cprj_work1,-1.0d0,1)
2843 :
2844 : ! Xout = Xin + sum_ai pai cprj_work
2845 94950 : if (present(Xout)) then
2846 0 : call xgBlock_copy(Xin,Xout)
2847 0 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work1,Xout,work_mpi)
2848 : else ! in place version
2849 94950 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work1,Xin,work_mpi)
2850 : end if
2851 :
2852 94950 : end subroutine xg_nonlop_getSm1X
2853 :
2854 450870 : subroutine xg_nonlop_getHmeSX(xg_nonlop,Xin,cprjin,Xout,eigen,cprj_work,work_mpi,no_H)
2855 :
2856 : use iso_c_binding
2857 :
2858 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2859 : type(xgBlock_t), intent(in) :: Xin,eigen,cprjin
2860 : type(xgBlock_t), intent(inout) :: Xout,cprj_work,work_mpi
2861 : logical,optional,intent(in) :: no_H
2862 :
2863 : real(dp) :: tsec(2)
2864 : integer :: nblocks,shift
2865 : integer :: nrows,ncols,nrows_out,ncols_out
2866 : integer :: nrows_diag,ncols_diag
2867 : integer :: nrows_cprj,ncols_cprj
2868 : integer :: nrows_cprj_work,ncols_cprj_work
2869 : integer :: nspinor
2870 : logical :: no_H_
2871 : type(xgBlock_t) :: cprj_work_spinor
2872 :
2873 75145 : call timab(tim_getHmeSX,1,tsec)
2874 :
2875 75145 : if (.not.xg_nonlop%paw) then
2876 0 : ABI_ERROR('Not implemented with paw=False.')
2877 : end if
2878 :
2879 75145 : nblocks = xmpi_comm_size(comm(cprjin))
2880 :
2881 75145 : nspinor = xg_nonlop%nspinor
2882 :
2883 75145 : call xgBlock_getsize(Xin,nrows,ncols)
2884 75145 : call xgBlock_getsize(Xout,nrows_out,ncols_out)
2885 75145 : call xgBlock_getsize(eigen,nrows_diag,ncols_diag)
2886 75145 : call xgBlock_getsize(cprjin,nrows_cprj,ncols_cprj)
2887 75145 : call xgBlock_getsize(cprj_work,nrows_cprj_work,ncols_cprj_work)
2888 75145 : if (ncols/=nrows_diag.or.ncols*nspinor/=nblocks*ncols_cprj.or.ncols_cprj/=ncols_cprj_work.or.ncols/=ncols_out) then
2889 0 : ABI_ERROR('wrong ncols')
2890 : end if
2891 75145 : if (nrows/=nrows_out) then
2892 0 : ABI_ERROR('nrows/=nrows_out')
2893 : end if
2894 75145 : if (nrows_cprj/=nrows_cprj_work) then
2895 0 : ABI_ERROR('nrows_cprj/=nrows_cprj_work')
2896 : end if
2897 75145 : if (ncols_diag/=1) then
2898 0 : ABI_ERROR('ncols_diag should be one')
2899 : end if
2900 :
2901 : ! cprj_work = sum_j Saij cprjin
2902 75145 : call xgBlock_zero(cprj_work)
2903 75145 : call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Sij%self,cprjin,cprj_work)
2904 :
2905 : ! cprj_work = - e cprj_work = -e sum_j Saij cprjin
2906 75145 : shift = xg_nonlop%me_band*ncols_cprj/xg_nonlop%nspinor
2907 75145 : call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
2908 75145 : call xgBlock_ymax(cprj_work_spinor,eigen,shift,nblocks)
2909 :
2910 75145 : no_H_=.False.
2911 75145 : if (present(no_H)) then
2912 12920 : no_H_ = no_H
2913 : end if
2914 12920 : if (.not.no_H_) then
2915 : ! cprj_work = sum_j Daij cprjin + cprj_work
2916 62225 : call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Dij_spin,cprjin,cprj_work)
2917 : end if
2918 :
2919 : ! Xout = Xout + sum_ai pai cprj_work
2920 75145 : call xg_nonlop_apply_prj(xg_nonlop,cprj_work,Xout,work_mpi)
2921 :
2922 : ! Xout = Xout - e Xin
2923 75145 : call xgBlock_yxmax(Xout,eigen,Xin)
2924 :
2925 75145 : call timab(tim_getHmeSX,2,tsec)
2926 :
2927 75145 : end subroutine xg_nonlop_getHmeSX
2928 : !!***
2929 :
2930 : !!****f* m_xg_nonlop/xg_nonlop_forces
2931 : !! NAME
2932 : !!
2933 : !! FUNCTION
2934 : !!
2935 : !! INPUTS
2936 : !!
2937 19100 : subroutine xg_nonlop_forces_stress(xg_nonlop,Xin,cprjin,cprj_work,eigen,forces,stress,gprimd)
2938 :
2939 : use m_geometry, only : strconv
2940 :
2941 : type(xg_nonlop_t), intent(in) :: xg_nonlop
2942 : type(xgBlock_t), intent(in) :: Xin,eigen
2943 : type(xgBlock_t), intent(in) :: cprjin
2944 : type(xgBlock_t), intent(inout) :: cprj_work
2945 : type(xgBlock_t), optional, intent(inout) :: forces
2946 : type(xgBlock_t), optional, intent(inout) :: stress
2947 : real(dp), optional, intent(in) :: gprimd(:,:)
2948 :
2949 : real(dp) :: tsec(2)
2950 : integer :: cplex,iband
2951 : integer :: nmpi,shift
2952 : integer :: nrows,ncols,ncols_cprj,ncols_cprj_nospin
2953 : integer :: nrows_diag,ncols_diag
2954 : integer :: nspinor,space_cprj
2955 :
2956 : type(xg_t) :: cprj_deriv,work_mpi_deriv,dot,dot_all
2957 19100 : real(dp), pointer :: dot_(:,:),dot_all_(:,:)
2958 : logical :: do_forces,do_stress
2959 : real(dp) :: work(6)
2960 19100 : real(dp), pointer :: stress_(:,:)
2961 : type(xgBlock_t) :: cprjin_spinor,cprj_work_spinor
2962 :
2963 19100 : call timab(tim_forces_stress,1,tsec)
2964 :
2965 19100 : call timab(tim_fst_start,1,tsec)
2966 :
2967 19100 : if (comm(Xin)/=xg_nonlop%comm_band) then
2968 0 : ABI_ERROR('wrong communicator')
2969 : end if
2970 :
2971 19100 : nmpi = xmpi_comm_size(comm(Xin))
2972 19100 : nspinor = xg_nonlop%nspinor
2973 :
2974 19100 : call xgBlock_getsize(Xin,nrows,ncols)
2975 19100 : call xgBlock_getsize(eigen,nrows_diag,ncols_diag)
2976 19100 : if (ncols/=nrows_diag) then
2977 0 : ABI_ERROR('wrong ncols')
2978 : end if
2979 19100 : if (ncols_diag/=1) then
2980 0 : ABI_ERROR('ncols_diag should be one')
2981 : end if
2982 :
2983 19100 : ncols_cprj = ncols*nspinor/nmpi
2984 19100 : ncols_cprj_nospin = ncols/nmpi
2985 :
2986 19100 : space_cprj = xg_nonlop%space_cprj
2987 :
2988 19100 : do_forces = .false.
2989 19100 : if (present(forces)) then
2990 18300 : do_forces = .true.
2991 18300 : if (rows(forces)/=3*xg_nonlop%natom) then
2992 0 : ABI_ERROR('rows(forces)/=3*natom')
2993 : end if
2994 18300 : if (cols(forces)/=ncols) then
2995 0 : ABI_ERROR('cols(forces)/=ncols')
2996 : end if
2997 : end if
2998 :
2999 19100 : do_stress = .false.
3000 19100 : if (present(stress)) then
3001 1140 : do_stress = .true.
3002 1140 : if (.not.present(gprimd)) then
3003 0 : ABI_ERROR('If stress is present, gprimd must be present too')
3004 : end if
3005 1140 : if (rows(stress)/=6) then
3006 0 : ABI_ERROR('rows(stress)/=6')
3007 : end if
3008 1140 : if (cols(stress)/=ncols) then
3009 0 : ABI_ERROR('cols(stress)/=ncols')
3010 : end if
3011 : end if
3012 :
3013 19100 : call xgBlock_zero(cprj_work)
3014 19100 : if (xg_nonlop%paw) then
3015 : ! cprj_work = sum_j Saij cprjin
3016 17212 : call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Sij%self,cprjin,cprj_work)
3017 : ! cprj_work = - e cprj_work = -e sum_j Saij cprjin
3018 17212 : shift = xg_nonlop%me_band*ncols_cprj_nospin
3019 17212 : call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
3020 17212 : call xgBlock_ymax(cprj_work_spinor,eigen,shift,nmpi)
3021 : end if
3022 :
3023 : ! cprj_work = sum_j Daij cprjin + cprj_work
3024 19100 : if (xg_nonlop%paw) then
3025 17212 : call xg_nonlop_apply_Aij(xg_nonlop,xg_nonlop%Dij_spin,cprjin,cprj_work)
3026 : else
3027 1888 : call xg_nonlop_apply_diag(xg_nonlop,xg_nonlop%ekb%self,cprjin,cprj_work)
3028 : end if
3029 :
3030 19100 : call timab(tim_fst_start,2,tsec)
3031 :
3032 19100 : if (do_forces) then
3033 :
3034 18300 : call xg_init(cprj_deriv ,space_cprj,3*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
3035 18300 : call xg_init(work_mpi_deriv,space_cprj,3*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
3036 :
3037 18300 : call timab(tim_fst_cprj_deriv_f,1,tsec)
3038 18300 : call xg_nonlop_getcprj_deriv(xg_nonlop,Xin,cprj_deriv%self,work_mpi_deriv%self,DERIV_ATOM)
3039 18300 : call timab(tim_fst_cprj_deriv_f,2,tsec)
3040 :
3041 18300 : call xg_free(work_mpi_deriv)
3042 :
3043 18300 : call xgBlock_zero(forces)
3044 :
3045 18300 : call timab(tim_fst_mult_cprj_f,1,tsec)
3046 18300 : call xg_nonlop_mult_cprj_forces(xg_nonlop,cprj_work,cprj_deriv%self,forces)
3047 18300 : call timab(tim_fst_mult_cprj_f,2,tsec)
3048 :
3049 18300 : call xg_free(cprj_deriv)
3050 :
3051 : end if
3052 :
3053 19100 : if (do_stress) then
3054 :
3055 1140 : call xg_init(cprj_deriv ,space_cprj,6*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
3056 1140 : call xg_init(work_mpi_deriv,space_cprj,6*xg_nonlop%cprjdim,ncols_cprj,comm=xg_nonlop%comm_band)
3057 :
3058 1140 : call timab(tim_fst_cprj_deriv_str,1,tsec)
3059 1140 : call xg_nonlop_getcprj_deriv(xg_nonlop,Xin,cprj_deriv%self,work_mpi_deriv%self,DERIV_STRESS)
3060 1140 : call timab(tim_fst_cprj_deriv_str,2,tsec)
3061 :
3062 1140 : call xg_free(work_mpi_deriv)
3063 :
3064 1140 : call xgBlock_zero(stress)
3065 :
3066 1140 : call timab(tim_fst_mult_cprj_str,1,tsec)
3067 1140 : call xg_nonlop_mult_cprj_stress(xg_nonlop,cprj_work,cprj_deriv%self,stress)
3068 1140 : call timab(tim_fst_mult_cprj_str,2,tsec)
3069 :
3070 1140 : call xg_free(cprj_deriv)
3071 :
3072 1140 : call timab(tim_fst_work_str,1,tsec)
3073 1140 : call xg_init(dot,space_cprj,ncols_cprj_nospin,1)
3074 :
3075 1140 : call xgBlock_reshape_spinor(cprjin,cprjin_spinor,nspinor,COLS2ROWS)
3076 1140 : call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
3077 1140 : call xgBlock_colwiseDotProduct(cprjin_spinor,cprj_work_spinor,dot%self,comm_loc=xmpi_comm_null)
3078 :
3079 1140 : cplex=1
3080 1140 : if (space_cprj==SPACE_C) cplex=2
3081 :
3082 1140 : call xg_init(dot_all,space_cprj,ncols,1)
3083 1140 : if (xmpi_comm_size(xg_nonlop%comm_band)>1) then
3084 768 : call xgBlock_zero(dot_all%self)
3085 768 : call xgBlock_reverseMap(dot%self,dot_)
3086 768 : call xgBlock_reverseMap(dot_all%self,dot_all_)
3087 768 : shift = cplex*xg_nonlop%me_band*ncols_cprj_nospin
3088 2752 : do iband=1,ncols_cprj_nospin
3089 2752 : dot_all_(1+cplex*(iband-1)+shift,1) = dot_(1+cplex*(iband-1),1)
3090 : end do
3091 768 : call xgBlock_mpi_sum(dot_all%self,comm=xg_nonlop%comm_band)
3092 : else
3093 372 : call xgBlock_reverseMap(dot%self,dot_all_)
3094 : end if
3095 :
3096 1140 : call xgBlock_reverseMap(stress,stress_)
3097 :
3098 11208 : do iband=1,ncols
3099 70476 : work = stress_(:,iband)
3100 10068 : call strconv(work,gprimd,work)
3101 40272 : stress_(1:3,iband) = work(1:3) - dot_all_(1+cplex*(iband-1),1)
3102 41412 : stress_(4:6,iband) = work(4:6)
3103 : end do
3104 :
3105 1140 : call xg_free(dot)
3106 1140 : call xg_free(dot_all)
3107 :
3108 1140 : call timab(tim_fst_work_str,2,tsec)
3109 :
3110 : end if
3111 :
3112 19100 : call timab(tim_forces_stress,2,tsec)
3113 :
3114 19100 : end subroutine xg_nonlop_forces_stress
3115 : !!***
3116 :
3117 18300 : subroutine xg_nonlop_mult_cprj_forces(xg_nonlop,cprj,cprj_deriv,forces)
3118 :
3119 : type(xg_nonlop_t), intent(in) :: xg_nonlop
3120 : type(xgBlock_t), intent(in) :: cprj,cprj_deriv
3121 : type(xgBlock_t), intent(inout) :: forces
3122 :
3123 : !real(dp) :: tsec(2)
3124 : integer :: ia,idir,ilmn,iband,iband_spinor,my_iband,itypat,nlmn,nattyp_i
3125 : integer :: ispinor,iforces,icprj,icprj_deriv
3126 : integer :: ncols_cprj,ncols_cprj_nospin
3127 : integer :: nspinor
3128 : integer :: shift_itypat,shift_itypat_nlmn,shift_itypat_3nlmn
3129 :
3130 18300 : real(dp), pointer :: forces_(:,:)
3131 18300 : complex(dp), pointer :: cprj_(:,:),cprj_deriv_(:,:)
3132 18300 : real(dp), pointer :: cprj_real(:,:),cprj_deriv_real(:,:)
3133 : real(dp) :: forces_tmp
3134 :
3135 18300 : nspinor = xg_nonlop%nspinor
3136 :
3137 18300 : ncols_cprj = cols(cprj)
3138 18300 : ncols_cprj_nospin = ncols_cprj/nspinor
3139 :
3140 18300 : call xgBlock_reverseMap(forces,forces_)
3141 :
3142 28903 : select case(xg_nonlop%space_cprj)
3143 :
3144 : case (SPACE_C)
3145 :
3146 10603 : call xgBlock_reverseMap(cprj,cprj_)
3147 10603 : call xgBlock_reverseMap(cprj_deriv,cprj_deriv_)
3148 :
3149 10603 : shift_itypat=0
3150 10603 : shift_itypat_nlmn=0
3151 10603 : shift_itypat_3nlmn=0
3152 : !$omp parallel default (none) &
3153 : !$omp& shared(xg_nonlop,forces_,cprj_deriv_,cprj_), &
3154 : !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_3nlmn,ncols_cprj_nospin,nspinor), &
3155 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,iforces,my_iband), &
3156 : !$omp& private(iband_spinor,icprj,icprj_deriv,forces_tmp)
3157 32376 : do itypat = 1, xg_nonlop%ntypat
3158 21773 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
3159 21773 : nattyp_i = xg_nonlop%nattyp(itypat)
3160 32376 : if (nattyp_i>0) then
3161 : !$omp do collapse(3)
3162 91565 : do iband=1,ncols_cprj_nospin
3163 163021 : do ia = 1, nattyp_i
3164 356232 : do idir=1,3
3165 : forces_tmp = zero
3166 512880 : do ispinor=1,nspinor
3167 3146064 : do ilmn=1,nlmn
3168 2633184 : iband_spinor = ispinor + nspinor*(iband-1)
3169 2633184 : icprj = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
3170 2633184 : icprj_deriv = ilmn + nlmn*(idir-1) + 3*nlmn*(ia-1) + shift_itypat_3nlmn
3171 : forces_tmp = forces_tmp &
3172 2931696 : & + 2 * dble(conjg(cprj_deriv_(icprj_deriv,iband_spinor))*cprj_(icprj,iband_spinor))
3173 : end do
3174 : end do
3175 214368 : iforces = idir + 3*(ia-1) + shift_itypat
3176 214368 : my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
3177 285824 : forces_(iforces,my_iband) = forces_(iforces,my_iband) + forces_tmp
3178 : end do
3179 : end do
3180 : end do
3181 : !$omp end do
3182 21157 : shift_itypat = shift_itypat + 3*nattyp_i
3183 21157 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
3184 21157 : shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
3185 : end if
3186 : end do
3187 : !$omp end parallel
3188 :
3189 : case (SPACE_R)
3190 :
3191 7697 : call xgBlock_reverseMap(cprj,cprj_real)
3192 7697 : call xgBlock_reverseMap(cprj_deriv,cprj_deriv_real)
3193 :
3194 7697 : shift_itypat=0
3195 7697 : shift_itypat_nlmn=0
3196 7697 : shift_itypat_3nlmn=0
3197 : !$omp parallel default (none) &
3198 : !$omp& shared(xg_nonlop,forces_,cprj_deriv_real,cprj_real), &
3199 : !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_3nlmn,ncols_cprj_nospin,nspinor), &
3200 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,iforces,my_iband), &
3201 : !$omp& private(iband_spinor,icprj,icprj_deriv,forces_tmp)
3202 23074 : do itypat = 1, xg_nonlop%ntypat
3203 15377 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
3204 15377 : nattyp_i = xg_nonlop%nattyp(itypat)
3205 23074 : if (nattyp_i>0) then
3206 : !$omp do collapse(3)
3207 50357 : do iband=1,ncols_cprj_nospin
3208 85373 : do ia = 1, nattyp_i
3209 175044 : do idir=1,3
3210 : forces_tmp = zero
3211 210096 : do ispinor=1,nspinor
3212 1648224 : do ilmn=1,nlmn
3213 1438128 : iband_spinor = ispinor + nspinor*(iband-1)
3214 1438128 : icprj = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
3215 1438128 : icprj_deriv = ilmn + nlmn*(idir-1) + 3*nlmn*(ia-1) + shift_itypat_3nlmn
3216 : forces_tmp = forces_tmp &
3217 1543176 : & + 2 * cprj_deriv_real(icprj_deriv,iband_spinor)*cprj_real(icprj,iband_spinor)
3218 : end do
3219 : end do
3220 105048 : iforces = idir + 3*(ia-1) + shift_itypat
3221 105048 : my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
3222 140064 : forces_(iforces,my_iband) = forces_(iforces,my_iband) + forces_tmp
3223 : end do
3224 : end do
3225 : end do
3226 : !$omp end do
3227 15377 : shift_itypat = shift_itypat + 3*nattyp_i
3228 15377 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
3229 15377 : shift_itypat_3nlmn = shift_itypat_3nlmn + nattyp_i*3*nlmn
3230 : end if
3231 : end do
3232 : !$omp end parallel
3233 :
3234 : case default
3235 18300 : ABI_ERROR("Wrong space")
3236 :
3237 : end select
3238 :
3239 18300 : call xgBlock_mpi_sum(forces,comm=xg_nonlop%comm_band)
3240 :
3241 18300 : end subroutine xg_nonlop_mult_cprj_forces
3242 :
3243 : !!****f* m_xg_nonlop/xg_nonlop_stress
3244 : !! NAME
3245 : !!
3246 : !! FUNCTION
3247 : !!
3248 : !! INPUTS
3249 : !!
3250 1140 : subroutine xg_nonlop_mult_cprj_stress(xg_nonlop,cprj,cprj_deriv,stress)
3251 :
3252 : type(xg_nonlop_t), intent(in) :: xg_nonlop
3253 : type(xgBlock_t), intent(in) :: cprj
3254 : type(xgBlock_t), intent(in) :: cprj_deriv
3255 : type(xgBlock_t), intent(inout) :: stress
3256 :
3257 : !real(dp) :: tsec(2)
3258 : integer :: ia,idir,ilmn,iband,iband_spinor,my_iband,itypat,nlmn,nattyp_i
3259 : integer :: ispinor,icprj,icprj_deriv
3260 : integer :: ncols_cprj,ncols_cprj_nospin,nspinor
3261 : integer :: shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn
3262 :
3263 1140 : complex(dp), pointer :: cprj_(:,:),cprj_deriv_(:,:)
3264 1140 : real(dp), pointer :: cprj_real(:,:),cprj_deriv_real(:,:)
3265 1140 : real(dp), pointer :: stress_(:,:)
3266 : real(dp) :: stress_tmp
3267 :
3268 : ! call timab(tim_getHmeSX,1,tsec)
3269 :
3270 1140 : nspinor = xg_nonlop%nspinor
3271 :
3272 1140 : ncols_cprj = cols(cprj)
3273 1140 : ncols_cprj_nospin = ncols_cprj/nspinor
3274 :
3275 1140 : call xgBlock_reverseMap(stress,stress_)
3276 :
3277 1871 : select case(xg_nonlop%space_cprj)
3278 :
3279 : case (SPACE_C)
3280 :
3281 731 : call xgBlock_reverseMap(cprj,cprj_)
3282 731 : call xgBlock_reverseMap(cprj_deriv,cprj_deriv_)
3283 :
3284 731 : shift_itypat=0
3285 731 : shift_itypat_nlmn=0
3286 731 : shift_itypat_6nlmn=0
3287 : !$omp parallel default (none) &
3288 : !$omp& shared(xg_nonlop,stress_,cprj_deriv_,cprj_), &
3289 : !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn,ncols_cprj_nospin,nspinor), &
3290 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,my_iband), &
3291 : !$omp& private(iband_spinor,icprj,icprj_deriv,stress_tmp)
3292 2176 : do itypat = 1, xg_nonlop%ntypat
3293 1445 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
3294 1445 : nattyp_i = xg_nonlop%nattyp(itypat)
3295 2176 : if (nattyp_i>0) then
3296 : !$omp do collapse(2)
3297 7309 : do iband=1,ncols_cprj_nospin
3298 42685 : do idir=1,6
3299 : stress_tmp = zero
3300 83472 : do ispinor=1,nspinor
3301 138288 : do ia = 1, nattyp_i
3302 634560 : do ilmn=1,nlmn
3303 531648 : iband_spinor = ispinor + nspinor*(iband-1)
3304 531648 : icprj = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
3305 531648 : icprj_deriv = ilmn + nlmn*(idir-1) + 6*nlmn*(ia-1) + shift_itypat_6nlmn
3306 : stress_tmp = stress_tmp &
3307 586464 : & + 2 * dble(conjg(cprj_deriv_(icprj_deriv,iband_spinor))*cprj_(icprj,iband_spinor))
3308 : end do
3309 : end do
3310 : end do
3311 35376 : my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
3312 41272 : stress_(idir,my_iband) = stress_(idir,my_iband) + stress_tmp
3313 : end do
3314 : end do
3315 : !$omp end do
3316 1413 : shift_itypat = shift_itypat + 6*nattyp_i
3317 1413 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
3318 1413 : shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
3319 : end if
3320 : end do
3321 : !$omp end parallel
3322 :
3323 : case (SPACE_R)
3324 :
3325 409 : call xgBlock_reverseMap(cprj,cprj_real)
3326 409 : call xgBlock_reverseMap(cprj_deriv,cprj_deriv_real)
3327 :
3328 409 : shift_itypat=0
3329 409 : shift_itypat_nlmn=0
3330 409 : shift_itypat_6nlmn=0
3331 : !$omp parallel default (none) &
3332 : !$omp& shared(xg_nonlop,stress_,cprj_deriv_real,cprj_real), &
3333 : !$omp& firstprivate(shift_itypat,shift_itypat_nlmn,shift_itypat_6nlmn,ncols_cprj_nospin,nspinor), &
3334 : !$omp& private(itypat,nattyp_i,nlmn,ia,ilmn,idir,my_iband), &
3335 : !$omp& private(iband_spinor,icprj,icprj_deriv,stress_tmp)
3336 1210 : do itypat = 1, xg_nonlop%ntypat
3337 801 : nlmn = xg_nonlop%nlmn_ntypat(itypat)
3338 801 : nattyp_i = xg_nonlop%nattyp(itypat)
3339 1210 : if (nattyp_i>0) then
3340 : !$omp do collapse(2)
3341 3653 : do iband=1,ncols_cprj_nospin
3342 20765 : do idir=1,6
3343 : stress_tmp = zero
3344 34224 : do ispinor=1,nspinor
3345 51552 : do ia = 1, nattyp_i
3346 303720 : do ilmn=1,nlmn
3347 269280 : iband_spinor = ispinor + nspinor*(iband-1)
3348 269280 : icprj = ilmn + nlmn*(ia-1) + shift_itypat_nlmn
3349 269280 : icprj_deriv = ilmn + nlmn*(idir-1) + 6*nlmn*(ia-1) + shift_itypat_6nlmn
3350 : stress_tmp = stress_tmp &
3351 286608 : & + 2 * cprj_deriv_real(icprj_deriv,iband_spinor)*cprj_real(icprj,iband_spinor)
3352 : end do
3353 : end do
3354 : end do
3355 17112 : my_iband = iband + xg_nonlop%me_band*ncols_cprj_nospin
3356 19964 : stress_(idir,my_iband) = stress_(idir,my_iband) + stress_tmp
3357 : end do
3358 : end do
3359 : !$omp end do
3360 801 : shift_itypat = shift_itypat + 6*nattyp_i
3361 801 : shift_itypat_nlmn = shift_itypat_nlmn + nattyp_i*nlmn
3362 801 : shift_itypat_6nlmn = shift_itypat_6nlmn + nattyp_i*6*nlmn
3363 : end if
3364 : end do
3365 : !$omp end parallel
3366 :
3367 : case default
3368 1140 : ABI_ERROR("Wrong space")
3369 :
3370 : end select
3371 :
3372 1140 : call xgBlock_mpi_sum(stress,comm=xg_nonlop%comm_band)
3373 :
3374 :
3375 : ! call timab(tim_getHmeSX,2,tsec)
3376 :
3377 1140 : end subroutine xg_nonlop_mult_cprj_stress
3378 : !!***
3379 :
3380 0 : end module m_xg_nonlop
3381 : !!***
|