Branch data Line data Source code
1 : : !!****m* ABINIT/m_precon
2 : : !! NAME
3 : : !! m_precon
4 : : !!
5 : : !! FUNCTION
6 : : !! Object used for chi0-based preconditioning of the SCF.
7 : : !!
8 : : !! SOURCE
9 : :
10 : : #if defined HAVE_CONFIG_H
11 : : #include "config.h"
12 : : #endif
13 : :
14 : : #include "abi_common.h"
15 : :
16 : : module m_precon
17 : :
18 : : use iso_c_binding
19 : : use defs_abitypes, only : MPI_type
20 : : use defs_basis
21 : : use m_dtset
22 : : use m_dtfil
23 : : use m_xmpi
24 : :
25 : : use defs_datatypes, only : pseudopotential_type
26 : : use defs_wvltypes
27 : : use m_atomdata, only : atom_length
28 : : use m_bandfft_kpt, only : bandfft_kpt, bandfft_kpt_get_ikpt, bandfft_kpt_set_ikpt
29 : : use m_cgprj, only : ctocprj
30 : : use m_cgtools
31 : : use m_dfpt_mkvxc, only : dfpt_mkvxc, dfpt_mkvxc_noncoll
32 : : use m_fft, only : fourdp, fourwf, fftpac, zerosym
33 : : use m_fftcore, only : sphereboundary
34 : : use m_fourier_interpol, only : transgrid
35 : : use m_iterative_solvers, only : cg_linear_solver, gmres_linear_solver
36 : : use m_kg, only : ph1d3d
37 : : use m_mkrho
38 : : use m_mpinfo, only : proc_distrb_cycle, proc_distrb_band
39 : : use m_occ, only : getnel
40 : : use m_paw_dmft
41 : : use m_pawrhoij, only : pawrhoij_type, pawrhoij_alloc, pawrhoij_free
42 : : use m_pawcprj, only : pawcprj_type, pawcprj_alloc, pawcprj_get, pawcprj_mpi_allgather, pawcprj_free
43 : : use m_pawang, only : pawang_type
44 : : use m_pawfgr, only : pawfgr_type
45 : : use m_pawtab, only : pawtab_type
46 : : use m_pawfgrtab, only : pawfgrtab_type
47 : : use m_paw_finegrid, only : pawgylmg
48 : : use m_paw_occupancies, only : pawmkrhoij
49 : : use m_paw_mkrho, only : pawmkrho
50 : : use m_paw_nhat, only : pawsushat
51 : : use m_prep_kgb, only : prep_getghc, prep_index_wavef_bandpp, prep_fourwf
52 : : use m_spacepar, only : symrhg
53 : :
54 : : implicit none
55 : : private
56 : :
57 : : type, public :: precon_object
58 : : integer :: iprcel
59 : : real(dp) :: dielng, diemix
60 : : !Geometry :
61 : : real(dp) :: gprimd(3, 3), rprimd(3, 3), gmet(3, 3), rmet(3, 3)
62 : : real(dp) :: ucvol, dvol
63 : : !PAW :
64 : : type(pseudopotential_type), pointer :: psps
65 : : integer :: unpaw
66 : : integer, pointer :: dimcprj(:), mcprj, usecprj
67 : : type(pawcprj_type), pointer :: cprj(:, :)
68 : : type(pawang_type), pointer :: pawang
69 : : type(pawfgr_type), pointer :: pawfgr
70 : : type(pawfgrtab_type), pointer :: pawfgrtab(:)
71 : : type(pawtab_type), pointer :: pawtab(:)
72 : : real(dp), pointer :: ylm(:, :)
73 : : real(dp), pointer :: ylmgr(:, :, :)
74 : : !To compute (weighted) densities and other quantities :
75 : : real(dp), pointer :: fermie
76 : : real(dp), pointer :: cg(:, :), eigen(:), occ(:), ph1d(:, :), phnons(:, :, :)
77 : : integer, pointer :: kg(:, :), npwarr(:), irrzon(:, :, :)
78 : : integer, pointer :: atindx(:), atindx1(:), nattyp(:)
79 : : integer, pointer :: symrec(:, :, :), indsym(:, :, :)
80 : : real(dp), pointer :: xred(:, :)
81 : : !For ffts :
82 : : integer :: nfftprc ! Number of fft grid points for preconditioned quantities (densities and/or potentials).
83 : : integer :: ngfftprc(18) ! All needed information about the 3D FFT for preconditioned quantities.
84 : : !For Kxc :
85 : : integer :: nkxc
86 : : real(dp), pointer :: kxc(:, :)
87 : : real(dp), pointer :: rhor(:, :)
88 : : real(dp), pointer :: vxc(:, :)
89 : :
90 : : !Logical variables :
91 : : logical :: use_precon
92 : : logical :: use_ldos
93 : : logical :: use_paw_rhoij
94 : : logical :: use_dos
95 : : logical :: use_kxc
96 : : logical :: use_ridgereg
97 : : logical :: use_indices_arrays
98 : : logical :: use_precomputed_rhoi
99 : : logical :: use_precomputed_psii
100 : :
101 : : !For LDOS preconditioner :
102 : : real(dp) :: tdos
103 : : real(dp), allocatable :: ldos(:, :)
104 : : real(dp), allocatable :: dos(:)
105 : :
106 : : !Usefull
107 : : integer, allocatable :: cg_indices(:, :, :, :)
108 : : integer, allocatable :: kg_indices(:, :)
109 : :
110 : : !Array to store precomputed ffts of cg :
111 : : real(dp), allocatable :: precomputed_rhoi(:, :, :)
112 : : integer, allocatable :: precomputed_rhoi_indices(:, :, :)
113 : : real(dp), allocatable :: precomputed_psii(:, :, :, :)
114 : : integer, allocatable :: precomputed_psii_indices(:, :, :)
115 : :
116 : : !Preconditioner parameters
117 : : integer :: precon_verbose
118 : : !Linear solver parameters
119 : : integer :: linsolve_maxiter
120 : : real(dp) :: linsolve_rtol, ridge_param
121 : : !chi0_diag/quasidiag parameters
122 : : real(dp) :: deigvals_tol_fp
123 : : real(dp) :: precon_tsmear
124 : :
125 : : contains
126 : : procedure :: init => precon_init ! Initialize the precon_object.
127 : : procedure :: init_kxc => precon_init_kxc ! Initialize kxc in the precon_object.
128 : : procedure :: update => precon_update ! Update the precon_object according to iprcel.
129 : : procedure :: free => precon_free ! Dealocate arrays that are allocated in precon_init.
130 : :
131 : : procedure :: apply_dielmat => apply_dielmat ! Apply the dielectric matrix to an input vector.
132 : : procedure :: apply_adjdielmat => apply_adjdielmat ! Apply the adjoint dielectric matrix to an input vector.
133 : : procedure :: apply_precon => apply_precon ! Apply the preconditioner to an input vector.
134 : :
135 : : end type precon_object
136 : :
137 : : contains
138 : :
139 : : ! TODO :
140 : : ! - Debug apply_chi0_quasidiag
141 : : ! - Implement non-collinear magnetism with band paral (Hyprid preconditioner)
142 : : ! - Non-collinear magnetism: We assume nspinor=2 => nspden=4 and nsppol=2 => nspden=2, but we could have nspden=1 in both cases.
143 : : ! For now, it is enforced in chkinp.
144 : : ! - Compute the dos in an efficient way.
145 : :
146 : : !****f* m_precon/precon_init
147 : : !! NAME
148 : : !! precon_init
149 : : !!
150 : : !! FUNCTION
151 : : !! Initialize the precon_object.
152 : : !!
153 : : !! INPUTS
154 : : !! dtset = all input variables for this dataset
155 : : !! atindx = index table for atoms (see gstate.f)
156 : : !! atindx1 = index table for atoms, inverse of atindx (see gstate.f)
157 : : !! cg = wf in G space
158 : : !! cprj =
159 : : !! dimcprj = dimension of the cprj array
160 : : !! eigen = array of eigenvalues
161 : : !! fermie = fermi energie
162 : : !! gprimd = dimensional reciprocal space primitive translations
163 : : !! irrzon = irreducible zone data
164 : : !! kg = reduced planewave coordinates
165 : : !! nattyp = number of atoms of each type.
166 : : !! nfftmix = number of planewaves in the mixing/preconditioning grid
167 : : !! ngfftmix =
168 : : !! npwarr = number of planewaves and boundary planewaves at each k
169 : : !! pawang = paw angular mesh and related data
170 : : !! pawfgr =
171 : : !! pawfgrtab =
172 : : !! pawtab =
173 : : !! phnons = nonsymmorphic translation phases
174 : : !! psps = pseudopotential data
175 : : !! rprimd = dimensional real space primitive translations
176 : : !! ucvol = unit cell volume
177 : : !! xred = reduced dimensionless atomic coordinates
178 : : !!
179 : : !! SOURCE
180 [ - + - + : 20859 : subroutine precon_init(this, dtset, atindx, atindx1, cg, cprj, dimcprj, dtfil, eigen, fermie, &
- + - + ]
181 [ - + - + : 20859 : & gmet, gprimd, indsym, irrzon, kg, mcprj, nattyp, nfftmix, ngfftmix, npwarr, occ, pawang, pawfgr, pawfgrtab, &
- + - + -
+ - + - +
- + - + ]
182 [ - + - + : 20859 : & pawtab, ph1d, phnons, psps, rhor, rmet, rprimd, symrec, ucvol, usecprj, vxc, xred, ylm)
- + - + -
+ - + - +
- + - + -
+ - + - +
- + + - ]
183 : :
184 : : !Arguments ------------------------------------
185 : : class(precon_object), intent(out) :: this
186 : : !scalars
187 : : type(dataset_type),intent(in) :: dtset
188 : : real(dp), intent(in) :: ucvol
189 : : real(dp), intent(in), target :: fermie
190 : : integer, intent(in) :: nfftmix
191 : : integer, intent(in), target :: mcprj
192 : : integer, intent(in), target :: usecprj
193 : : !arrays
194 : : real(dp), intent(in) :: gprimd(:, :), rprimd(:, :), gmet(:, :), rmet(:, :)
195 : : integer, intent(in) :: ngfftmix(:)
196 : : integer, intent(in), target :: irrzon(:, :, :), kg(:, :), npwarr(:)
197 : : integer, intent(in), target :: atindx(:), atindx1(:), nattyp(:)
198 : : integer, intent(in), target :: symrec(:, :, :), indsym(:, :, :)
199 : : real(dp), intent(in), target :: cg(:, :), eigen(:), occ(:), phnons(:, :, :), ph1d(:, :)
200 : : real(dp), intent(in), target :: rhor(:, :), vxc(:, :)
201 : : real(dp), intent(in), target :: xred(:, :)
202 : : type(datafiles_type),intent(in) :: dtfil
203 : : type(pseudopotential_type), intent(in), target :: psps
204 : : integer, intent(in), target :: dimcprj(:)
205 : : type(pawcprj_type), intent(in), target :: cprj(:, :)
206 : : type(pawang_type), intent(in), target :: pawang
207 : : type(pawfgr_type), intent(in), target :: pawfgr
208 : : type(pawfgrtab_type), intent(in), target :: pawfgrtab(:)
209 : : type(pawtab_type), intent(in), target :: pawtab(:)
210 : : real(dp), intent(in), target :: ylm(:, :)
211 : :
212 : : ! *************************************************************************
213 : :
214 : 6953 : this%iprcel = dtset%iprcel
215 : 6953 : this%use_precon = .false.
216 : 6953 : this%use_kxc = .false.
217 : :
218 [ + + ]: 6953 : if (this%iprcel >= 200 .and. this%iprcel < 300) then
219 : :
220 : 2 : this%use_precon = .true.
221 : :
222 : : !Logical variables that describe the preconditioner :
223 : : ! 200 -> LDOS with RPA
224 : : ! 201 -> Kerker with DOS+ and DOS-
225 : : ! 202 -> Hybrid (LDOS+diag)
226 : : ! 203 -> Hybrid for antiferro (LDOS+quasidiag) - WIP - Not documented
227 : : ! 210 -> Kerker with dielng - Not documented
228 : : ! 211 -> Kerker with DOS - Not documented
229 : : ! 212 -> LDOS without RPA - Not documented
230 : : ! 299 -> No preconditioning - Not documented
231 : :
232 : : ! this%use_ldos = .true. activates the computation of the ldos.
233 : 2 : this%use_ldos = .false.
234 [ + + ]: 2 : if (this%iprcel == 200) this%use_ldos = .true.
235 [ - + ]: 2 : if (this%iprcel == 212) this%use_ldos = .true.
236 [ + + ]: 2 : if (this%iprcel == 202) this%use_ldos = .true.
237 [ - + ]: 2 : if (this%iprcel == 211) this%use_ldos = .true.
238 [ - + ]: 2 : if (this%iprcel == 201) this%use_ldos = .true.
239 : :
240 : 2 : this%use_paw_rhoij = .false.
241 : :
242 : : ! If this%use_dos = .true. we will use this%dos.
243 : 2 : this%use_dos = .false.
244 [ - + ]: 2 : if (this%iprcel == 211) this%use_dos = .true.
245 [ - + ]: 2 : if (this%iprcel == 201) this%use_dos = .true.
246 : :
247 : : ! this%use_kxc = .true. activates the use of the exchange and correlation kernel.
248 : : ! If this%use_kxc = .false. the RPA will be used.
249 : : this%use_kxc = .false.
250 [ - + ]: 2 : if (this%iprcel == 212) this%use_kxc = .true.
251 [ + + ]: 2 : if (this%iprcel == 202) this%use_kxc = .true.
252 : :
253 : : ! this%use_ridgereg = .true. activates the use of an adapted linear solver.
254 : 2 : this%use_ridgereg = .false.
255 : :
256 : : ! this%use_indices_arrays = .true. indicates that we will use the arrays this%cg_indices and this%kg_indices.
257 : 2 : this%use_indices_arrays = .false.
258 [ + + ]: 2 : if (this%iprcel == 202) this%use_indices_arrays = .true.
259 [ - + ]: 2 : if (this%iprcel == 203) this%use_indices_arrays = .true.
260 : :
261 : 2 : this%use_precomputed_rhoi = .false.
262 [ + + + - ]: 2 : if (this%iprcel == 202 .and. dtset%precon_in_memory==1) this%use_precomputed_rhoi = .true.
263 [ + + - + : 2 : if (this%iprcel == 202 .and. dtset%precon_in_memory==0 .and. dtset%npband>1) then
- - ]
264 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): With band parallelization precon_in_memory must be 1.")
265 : : end if
266 : :
267 : 2 : this%use_precomputed_psii = .false.
268 [ - + - - ]: 2 : if (this%iprcel == 203 .and. dtset%precon_in_memory==1) this%use_precomputed_psii = .true.
269 : :
270 : : ! Other than here, iprcel is only used in apply_chi0, apply_dielmat and apply_adjdielmat.
271 : :
272 : : !Constant data from dtset
273 : 2 : this%dielng = dtset%dielng
274 : 2 : this%diemix = dtset%diemix
275 : 2 : this%nfftprc = nfftmix ! FFT grid for preconditioned densities and/or potentials :
276 [ + + ]: 38 : this%ngfftprc = ngfftmix ! same grid as the one used for mixing.
277 : : !Other constants
278 : 2 : this%dvol = ucvol/this%nfftprc ! factor for integrals in real space (on the preconditioning FFT grid) : sum(f) * dvol ~ integral f
279 [ + + + + ]: 26 : this%gprimd = gprimd
280 [ + + + + ]: 26 : this%rprimd = rprimd
281 [ + + + + ]: 26 : this%gmet = gmet
282 [ + + + + ]: 26 : this%rmet = rmet
283 : 2 : this%ucvol = ucvol
284 : : !Pointers
285 : 2 : this%atindx => atindx
286 : 2 : this%atindx1 => atindx1
287 : 2 : this%cg => cg
288 : 2 : this%eigen => eigen
289 : 2 : this%fermie => fermie
290 : 2 : this%indsym => indsym
291 : 2 : this%irrzon => irrzon
292 : 2 : this%kg => kg
293 : 2 : this%nattyp => nattyp
294 : 2 : this%npwarr => npwarr
295 : 2 : this%occ => occ
296 : 2 : this%ph1d => ph1d
297 : 2 : this%phnons => phnons
298 : 2 : this%psps => psps
299 : 2 : this%rhor => rhor
300 : 2 : this%symrec => symrec
301 : 2 : this%vxc => vxc
302 : 2 : this%xred => xred
303 : :
304 : : !PAW :
305 [ - + ]: 2 : if (psps%usepaw==1) then
306 : 0 : this%unpaw = dtfil%unpaw
307 : 0 : this%cprj => cprj
308 : 0 : this%usecprj => usecprj
309 : 0 : this%dimcprj => dimcprj
310 : 0 : this%mcprj => mcprj
311 : 0 : this%pawang => pawang
312 : 0 : this%pawfgr => pawfgr
313 : 0 : this%pawfgrtab => pawfgrtab
314 : 0 : this%pawtab => pawtab
315 : 0 : this%ylm => ylm
316 : : end if
317 : :
318 : : !Initializing LDOS specific variables
319 [ + - ]: 2 : if (this%use_ldos) then
320 : : !Allocating the array containing ldos
321 [ - + + - : 8 : ABI_MALLOC(this%ldos, (this%nfftprc, dtset%nspden))
- + + - +
- + - - +
- + - + ]
322 : : end if
323 : :
324 [ - + ]: 2 : if (this%use_dos) then
325 : : !Allocating the array containing the dos
326 [ # # # # : 0 : ABI_MALLOC(this%dos, (dtset%nspden))
# # # # #
# # # #
# ]
327 : : end if
328 : :
329 : : !Initializing variables needed for Kxc
330 [ + + ]: 2 : if (this%use_kxc) then
331 : : !Preparing the allocation of Kxc
332 [ - + ]: 1 : if (dtset%xclevel==1) then !LDA
333 : 0 : this%nkxc = 2*min(dtset%nspden,2)-1
334 [ + - ]: 1 : else if (dtset%xclevel==2)then !GGA+...
335 [ - + ]: 1 : if (dtset%nspden==1) then
336 : 0 : this%nkxc = 7
337 [ + - ]: 1 : else if (dtset%nspden==2) then
338 : 1 : this%nkxc = 19
339 : : else
340 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): kxc not implemented for nspden > 2 (non-coll magn) in GGA")
341 : : end if
342 : : end if
343 : : end if
344 : :
345 : : !Preconditioner parameters
346 : 2 : this%precon_verbose = dtset%precon_verbose
347 : : !Linear solver parameters
348 : 2 : this%linsolve_maxiter = dtset%precon_ls_maxite
349 : 2 : this%linsolve_rtol = dtset%precon_ls_rtol
350 : : ! For inversion of non positive definite (adjointe) dielectric matrix
351 : 2 : this%ridge_param = 0.01
352 : :
353 : : !chi0_diag/quasidiag parameters
354 : 2 : this%deigvals_tol_fp = tol10
355 : 2 : this%precon_tsmear = max(dtset%precon_tsmear, dtset%tsmear)
356 : :
357 : : !Usefull : indices mapping arrays
358 [ + + ]: 2 : if (this%use_indices_arrays)then
359 [ + - - + : 6 : ABI_MALLOC(this%cg_indices, (2*dtset%nspinor, dtset%mband, dtset%nkpt, dtset%nsppol))
+ - - + +
- - + + -
- + + - +
- + - - +
- + - + ]
360 [ - + + - : 3 : ABI_MALLOC(this%kg_indices, (2, dtset%nkpt))
+ - + - -
+ - + -
+ ]
361 : : end if
362 [ + + ]: 2 : if (this%use_precomputed_rhoi) then
363 [ - + + - : 5 : ABI_MALLOC(this%precomputed_rhoi_indices, (dtset%mband, dtset%nkpt, dtset%nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + ]
364 : : end if
365 [ - + ]: 2 : if (this%use_precomputed_psii) then
366 [ # # # # : 0 : ABI_MALLOC(this%precomputed_psii_indices, (dtset%mband, dtset%nkpt, dtset%nsppol))
# # # # #
# # # # #
# # # # #
# # # ]
367 : : end if
368 : :
369 : : end if
370 : :
371 : 6953 : end subroutine precon_init
372 : :
373 : : !****f* m_precon/precon_init_kxc
374 : : !! NAME
375 : : !! precon_init_kxc
376 : : !!
377 : : !! FUNCTION
378 : : !! Initialize the exchange and correlation kernel (kxc) in the precon_object.
379 : : !! This is needed because kxc needs to be initialized at a specific time.
380 : : !!
381 : : !! INPUTS
382 : : !! kxc = exchange and correlation kernel.
383 : : !!
384 : : !! SOURCE
385 [ - + ]: 6953 : subroutine precon_init_kxc(this, kxc)
386 : :
387 : : !Arguments ------------------------------------
388 : : class(precon_object), intent(inout) :: this
389 : : real(dp), intent(in), target :: kxc(:, :)
390 : :
391 : : ! *************************************************************************
392 [ + + ]: 6953 : if (this%use_precon) then
393 [ + + ]: 2 : if (this%use_kxc) then
394 : 1 : this%kxc => kxc
395 : : end if
396 : : end if
397 : :
398 : 6953 : end subroutine precon_init_kxc
399 : :
400 : : !****f* m_precon/precon_update
401 : : !! NAME
402 : : !! precon_update
403 : : !!
404 : : !! FUNCTION
405 : : !! Update the precon_object :
406 : : !! For preconditioners using the LDOS (iprcel = 200 or 212) :
407 : : !! Compute the new ldos (local density of state) with current wavefunctions
408 : : !! and the new tdos (total density of state = integral of ldos).
409 : : !!
410 : : !! INPUTS
411 : : !! dtset = All input variables for this dataset.
412 : : !! mpi_enreg = Information about MPI parallelization.
413 : : !!
414 : : !! SOURCE
415 : 18 : subroutine precon_update(this, dtset, mpi_enreg)
416 : :
417 : : !Arguments ------------------------------------
418 : : class(precon_object), intent(inout) :: this
419 : : type(dataset_type), intent(in) :: dtset
420 : : type(MPI_type), intent(in) :: mpi_enreg
421 : :
422 : : !Local variables-------------------------------
423 : : integer :: ispden
424 : :
425 : : ! *************************************************************************
426 : :
427 [ + - ]: 18 : if (this%use_precon) then
428 : :
429 : : ! Indices in cg array
430 [ + + ]: 18 : if (this%use_indices_arrays) then
431 : 10 : call compute_cg_indices(dtset, mpi_enreg, this%npwarr, this%cg_indices)
432 : 10 : call compute_kg_indices(dtset, mpi_enreg, this%npwarr, this%kg_indices)
433 : : end if
434 : :
435 : : !LDOS
436 [ + - ]: 18 : if (this%use_ldos) then
437 : : !update ldos
438 : 18 : call compute_ldos(this, dtset, mpi_enreg, this%ldos)
439 : : !update tdos
440 [ + + ]: 60768 : this%tdos = sum(this%ldos(:, 1)) * this%dvol
441 : :
442 : : ! TODO : Extremely Inefficient way to compute the DOS ...
443 [ - + ]: 18 : if (this%use_dos) then
444 [ # # ]: 0 : do ispden = 1, dtset%nspden
445 [ # # ]: 0 : this%dos(ispden) = sum(this%ldos(:, ispden)) * this%dvol
446 : : end do
447 : : end if
448 : :
449 : : end if
450 : :
451 : : !Diag/Quasidiag chi0
452 [ - + ]: 18 : if (this%use_precomputed_psii) then
453 : 0 : call precompute_psii(this, dtset, mpi_enreg)
454 : : ! Will also precompute rhoi.
455 [ + + ]: 18 : elseif (this%use_precomputed_rhoi) then
456 : 10 : call precompute_rhoi(this, dtset, mpi_enreg)
457 : : end if
458 : :
459 : : end if
460 : 18 : end subroutine precon_update
461 : :
462 : : !****f* m_precon/precon_free_update
463 : : !! NAME
464 : : !! precon_update
465 : : !!
466 : : !! FUNCTION
467 : : !! Deallocates arrays that might have been allocated in 'precon_update'.
468 : : !!
469 : : !! INPUTS
470 : : !! dtset = All input variables for this dataset.
471 : : !! mpi_enreg = Information about MPI parallelization.
472 : : !!
473 : : !! SOURCE
474 : 18 : subroutine precon_free_update(this)
475 : :
476 : : !Arguments ------------------------------------
477 : : class(precon_object), intent(inout) :: this
478 : :
479 : : ! *************************************************************************
480 [ + - ]: 18 : if (this%use_precon) then
481 : :
482 [ + + ]: 18 : if (this%use_precomputed_rhoi) then
483 [ - + ]: 10 : ABI_FREE(this%precomputed_rhoi)
484 : : end if
485 [ - + ]: 18 : if (this%use_precomputed_psii) then
486 [ # # ]: 0 : ABI_FREE(this%precomputed_psii)
487 : : end if
488 : :
489 : : end if
490 : 18 : end subroutine precon_free_update
491 : :
492 : : !****f* m_precon/precon_free
493 : : !! NAME
494 : : !! precon_free
495 : : !!
496 : : !! FUNCTION
497 : : !! Dealocate arrays that are allocated in precon_init.
498 : : !!
499 : : !! SOURCE
500 : 6953 : subroutine precon_free(this)
501 : :
502 : : !Arguments ------------------------------------
503 : : class(precon_object), intent(inout) :: this
504 : :
505 : : ! *************************************************************************
506 [ + + ]: 6953 : if (this%use_precon) then
507 : :
508 [ + + ]: 2 : if (this%use_indices_arrays) then
509 [ - + ]: 1 : ABI_FREE(this%cg_indices)
510 [ - + ]: 1 : ABI_FREE(this%kg_indices)
511 : : end if
512 : :
513 [ + + ]: 2 : if (this%use_precomputed_rhoi) then
514 [ - + ]: 1 : ABI_FREE(this%precomputed_rhoi_indices)
515 : : end if
516 [ - + ]: 2 : if (this%use_precomputed_psii) then
517 [ # # ]: 0 : ABI_FREE(this%precomputed_psii_indices)
518 : : end if
519 : :
520 [ + - ]: 2 : if (this%use_ldos) then
521 : : !Deallocating the array containing ldos and tdos
522 [ - + ]: 2 : ABI_FREE(this%ldos)
523 : : end if
524 : :
525 [ - + ]: 2 : if (this%use_dos) then
526 [ # # ]: 0 : ABI_FREE(this%dos)
527 : : end if
528 : :
529 : : end if
530 : 6953 : end subroutine precon_free
531 : :
532 : : !****f* m_precon/compute_r
533 : : !! NAME
534 : : !! compute_r
535 : : !!
536 : : !! FUNCTION
537 : : !! Computes the array of r-vectors (in REDUCED coordinates).
538 : : !!
539 : : !! INPUTS
540 : : !! ngfft = All needed information about 3D FFT, see ~abinit/doc/variables/gstate/#ngfft.
541 : : !!
542 : : !! OUTPUTS
543 : : !! r_vectors(3, :) = 3 coordinates of the r_vectors.
544 : : !!
545 : : !! -unused-
546 : : !!
547 : : !! SOURCE
548 : : subroutine compute_r(ngfft, r_vectors)
549 : :
550 : : !Arguments ------------------------------------
551 : : real(dp), intent(out) :: r_vectors(:, :)
552 : : integer, intent(in) :: ngfft(:)
553 : :
554 : : !Local variables-------------------------------
555 : : integer :: n1, n2, n3, i1, i2, i3, i_r
556 : :
557 : : ! *************************************************************************
558 : :
559 : : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
560 : : do i3=1,n3
561 : : do i2=1,n2
562 : : do i1=1,n1
563 : : i_r = 1 + (i1-1) + (i2-1)*n1 + (i3-1)*n1*n2
564 : : r_vectors(1, i_r) = real(i1-1)/n1
565 : : r_vectors(2, i_r) = real(i2-1)/n2
566 : : r_vectors(3, i_r) = real(i3-1)/n3
567 : : end do
568 : : end do
569 : : end do
570 : :
571 : : end subroutine compute_r
572 : :
573 : : !****f* m_precon/get_r_vector
574 : : !! NAME
575 : : !! get_r_vector
576 : : !!
577 : : !! FUNCTION
578 : : !! Get the vector r (in REDUCED coordinates) of index ifft.
579 : : !!
580 : : !! INPUTS
581 : : !! ifft = Index of sought vector r.
582 : : !! ngfft = All needed information about 3D FFT, see ~abinit/doc/variables/gstate/#ngfft.
583 : : !!
584 : : !! OUTPUT
585 : : !! r(3) = sought vector r
586 : : !!
587 : : !! SOURCE
588 : : function get_r_vector(ifft, ngfft) result(r)
589 : :
590 : : !Arguments ------------------------------------
591 : : integer, intent(in) :: ifft
592 : : integer, intent(in) :: ngfft(:)
593 : :
594 : : !Local variables-------------------------------
595 : : integer :: n1, n2, n3, i1, i2, i3
596 : :
597 : : !Returned variable-------------------------------
598 : : real(dp) :: r(3)
599 : :
600 : : ! *************************************************************************
601 : :
602 : : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
603 : : i1 = modulo((ifft-1), n1) + 1
604 : : i2 = modulo((ifft-1)/n1, n2) + 1
605 : : i3 = ((ifft-1)/n1)/n2 + 1
606 : : r(1) = real(i1-1)/n1
607 : : r(2) = real(i2-1)/n2
608 : : r(3) = real(i3-1)/n3
609 : :
610 : : end function get_r_vector
611 : :
612 : : !****f* m_precon/get_g_vector
613 : : !! NAME
614 : : !! get_g_vector
615 : : !!
616 : : !! FUNCTION
617 : : !! Get the vector g (in REDUCED coordinates) of index ifft
618 : : !!
619 : : !! INPUTS
620 : : !! ifft = Index of sought vector g.
621 : : !! ngfft = All needed information about 3D FFT, see ~abinit/doc/variables/gstate/#ngfft.
622 : : !!
623 : : !! OUTPUT
624 : : !! g(3) = sought vector g
625 : : !!
626 : : !! SOURCE
627 [ - + - + ]: 303660 : function get_g_vector(ifft, ngfft) result(g)
628 : :
629 : : !Arguments ------------------------------------
630 : : integer, intent(in) :: ifft
631 : : integer, intent(in) :: ngfft(:)
632 : :
633 : : !Local variables-------------------------------
634 : : integer :: n1, n2, n3, i1, i2, i3
635 : :
636 : : !Returned variable-------------------------------
637 : : integer(dp) :: g(3)
638 : :
639 : : ! *************************************************************************
640 : :
641 : 303660 : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
642 : : ! (ifft-1) = (i1-1) + (i2-1)*n1 + (i3-1)*n1*n2
643 : 303660 : i1 = modulo(ifft-1, n1) +1
644 : 303660 : i2 = modulo((ifft-1)/n1, n2) +1
645 : 303660 : i3 = ((ifft-1)/n1)/n2 +1
646 : 303660 : g(1) = i1 - (i1/(n1/2+2))*n1-1
647 : 303660 : g(2) = i2 - (i2/(n2/2+2))*n2-1
648 : 303660 : g(3) = i3 - (i3/(n3/2+2))*n3-1
649 : :
650 : 303660 : end function get_g_vector
651 : :
652 : : !!***
653 : : !!****f* ABINIT/to_pauli
654 : : !! NAME
655 : : !! to_pauli
656 : : !!
657 : : !! FUNCTION
658 : : !! Basis change from the default spin-basis to the Pauli basis for potentials and densities
659 : : !! in the direct (r) space.
660 : : !!
661 : : !! INPUT/OUTPUT
662 : : !! opt = 0 : v is a potential
663 : : !! 1 : v is a density
664 : : !! v(nfft, nspden) = On input : Potential/density in the default spin-basis.
665 : : !! On output : Potential/density in the Pauli basis.
666 : : !!
667 : : !! SOURCE
668 [ - + ]: 128 : subroutine to_pauli(opt, v)
669 : : !Arguments ------------------------------------
670 : : real(dp), intent(inout) :: v(:, :)
671 : : integer :: opt
672 : : !Local variables-------------------------------
673 : : integer :: nspden
674 : 128 : real(dp), allocatable :: temp(:)
675 : :
676 : : ! *************************************************************************
677 : 128 : nspden = size(v, 2)
678 : :
679 : : !sigma_0, ... , sigma_3 are the Pauli matrices.
680 [ + + ]: 128 : if (opt == 0) then !v is a potential
681 [ + - ]: 55 : if (nspden == 2) then
682 : : !On input v(:, 1) is the spin-up potential and v(:, 2) is the spin-down potential.
683 : : !On output the entire potential is v(:, 1)*sigma_0 + v(:, 2)*sigma_3.
684 [ + + ]: 185680 : v(:, 1) = 0.5_dp*(v(:, 1) + v(:, 2))
685 [ + + ]: 185680 : v(:, 2) = v(:, 1) - v(:, 2)
686 [ # # ]: 0 : else if (nspden == 4) then
687 : : ! v(:, 1) | v(:, 3) + i*v(:, 4)
688 : : !On input the entire potential is --------------------|----------------------
689 : : ! v(:, 3) - i*v(:, 4) | v(:, 2)
690 : : ! (see dotprod_vn in m_cgtools)
691 : : !On output the entire potential is
692 : : ! v(:, 1)*sigma_0 + v(:, 2)*sigma_1 + v(:, 3)*sigma_2 + v(:, 4)*sigma_3
693 : : ! v(:, 1) + v(:, 4) | v(:, 2) - i*v(:, 3)
694 : : ! = --------------------|----------------------
695 : : ! v(:, 2) + i*v(:, 3) | v(:, 1) - v(:, 4)
696 : :
697 [ # # # # : 0 : ABI_MALLOC(temp, (size(v, 1)))
# # # # #
# # # ]
698 : :
699 [ # # ]: 0 : v(:, 1) = 0.5_dp*(v(:, 1) + v(:, 2))
700 [ # # # # : 0 : temp = v(:, 4)
# # # # ]
701 [ # # ]: 0 : v(:, 4) = v(:, 1) - v(:, 2) ! = 0.5_dp*(v(:, 1)_old - v(:, 2))
702 [ # # ]: 0 : v(:, 2) = v(:, 3)
703 [ # # ]: 0 : v(:, 3) = -temp
704 : :
705 [ # # ]: 0 : ABI_FREE(temp)
706 : : end if
707 : :
708 [ + - ]: 73 : else if (opt == 1) then !v is a density
709 [ + - ]: 73 : if (nspden == 2) then
710 : : !On input v(:, 1) is the total density and v(:, 2) is the spin-up density.
711 : : !On output v(:, 1) is the total density and v(:, 2) is the spin density.
712 [ + + ]: 246448 : v(:, 2) = 2*v(:, 2) - v(:, 1)
713 : : end if
714 : : !If nspden=4, the density is already given in the Pauli basis.
715 : : end if
716 : 128 : end subroutine to_pauli
717 : :
718 : : !!***
719 : : !!****f* ABINIT/from_pauli
720 : : !! NAME
721 : : !! from_pauli
722 : : !!
723 : : !! FUNCTION
724 : : !! Basis change from the Pauli basis to the Abinit default spin-basis for potentials and densities
725 : : !! in the real space.
726 : : !!
727 : : !! INPUT/OUTPUT
728 : : !! opt = 0 : v is a potential
729 : : !! 1 : v is a density
730 : : !! v(nfft, nspden) = On input : Potential/density in the Pauli basis
731 : : !! On output : Potential/density in the default Abinit spin-basis.
732 : : !!
733 : : !! SOURCE
734 [ - + ]: 73 : subroutine from_pauli(opt, v)
735 : : !Arguments ------------------------------------
736 : : real(dp), intent(inout) :: v(:, :)
737 : : integer :: opt
738 : : !Local variables-------------------------------
739 : : integer :: nspden
740 : 73 : real(dp), allocatable :: temp(:)
741 : :
742 : : ! *************************************************************************
743 : 73 : nspden = size(v, 2)
744 : :
745 : : !sigma_0, ... , sigma_3 are the Pauli matrices.
746 [ - + ]: 73 : if (opt == 0) then !v is a potential
747 [ # # ]: 0 : if (nspden == 2) then
748 : : !On input the entire potential is v(:, 1)*sigma_0 + v(:, 2)*sigma_3.
749 : : !On output v(:, 1) is the spin-up potential and v(:, 2) is the spin-down potential.
750 [ # # ]: 0 : v(:, 1) = v(:, 1) + v(:, 2)
751 [ # # ]: 0 : v(:, 2) = v(:, 1) - 2*v(:, 2)
752 [ # # ]: 0 : else if (nspden == 4) then
753 : :
754 : : !On input the entire potential is
755 : : ! v(:, 1)*sigma_0 + v(:, 2)*sigma_1 + v(:, 3)*sigma_2 + v(:, 4)*sigma_3
756 : : ! v(:, 1) + v(:, 4) | v(:, 2) - i*v(:, 3)
757 : : ! = --------------------|----------------------
758 : : ! v(:, 2) + i*v(:, 3) | v(:, 1) - v(:, 4)
759 : : !
760 : : ! v(:, 1) | v(:, 3) + i*v(:, 4)
761 : : !On output the entire potential is --------------------|----------------------
762 : : ! v(:, 3) - i*v(:, 4) | v(:, 2)
763 : : ! (see dotprod_vn in m_cgtools)
764 : :
765 [ # # # # : 0 : ABI_MALLOC(temp, (size(v, 1)))
# # # # #
# # # ]
766 : :
767 [ # # # # : 0 : temp = v(:, 2)
# # # # ]
768 [ # # ]: 0 : v(:, 2) = v(:, 1) - v(:, 4) ! = v(:, 1)_old - v(:, 4)_old
769 [ # # ]: 0 : v(:, 1) = v(:, 1) + v(:, 4) ! = v(:, 1)_old + v(:, 4)_old
770 [ # # ]: 0 : v(:, 4) = -v(:, 3) ! = -v(:, 3)_old
771 [ # # ]: 0 : v(:, 3) = temp ! = v(:, 2)_old
772 : :
773 [ # # ]: 0 : ABI_FREE(temp)
774 : :
775 : : end if
776 : :
777 [ + - ]: 73 : else if (opt == 1) then !v is a density
778 [ + - ]: 73 : if (nspden == 2) then
779 : : !On input v(:, 1) is the total density and v(:, 2) is the spin density.
780 : : !On output v(:, 1) is the total density and v(:, 2) is the spin-up density.
781 [ + + ]: 246448 : v(:, 2) = 0.5_dp*(v(:, 1) + v(:, 2))
782 : : end if
783 : : !If nspden=4, the density is already given in the Pauli basis.
784 : : end if
785 : 73 : end subroutine from_pauli
786 : :
787 : : !****f* m_precon/apply_vc
788 : : !! NAME
789 : : !! apply_vc
790 : : !!
791 : : !! FUNCTION
792 : : !! Apply the Coulomb kernel vc to a vector (in place) in the Pauli basis.
793 : : !!
794 : : !! INPUTS
795 : : !!
796 : : !! SIDE EFFECTS
797 : : !! vec_r (nfftprc, nspden) = Vector (in direct space) to which the Coulomb kernel vc is applied (in place).
798 : : !! When nspden > 1 vec_r is in the Pauli basis.
799 : : !!
800 : : !! SOURCE
801 : 90 : subroutine apply_vc(this, dtset, mpi_enreg, vec_r)
802 : : !Arguments ------------------------------------
803 : : class(precon_object), intent(in) :: this
804 : : type(dataset_type),intent(in) :: dtset
805 : : type(MPI_type), intent(in) :: mpi_enreg
806 : : !arrays
807 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
808 : :
809 : : !Local variables-------------------------------
810 : : integer :: ifft, ispden, cplex
811 : : real(dp) :: g_cart_2
812 : : integer :: n1, n2, n3
813 : 180 : real(dp) :: vec_g(2, this%nfftprc, 1)
814 : :
815 : : ! *************************************************************************
816 : :
817 : : !In the sigma_0, 1, 2, 3 (pauli) basis :
818 : : ! The sigma_0 component of the density is multiplied by 4pi/G^2
819 : : ! and the rest is 0.
820 : :
821 : 90 : cplex = 1 ! vec is REAL
822 : 90 : n1=this%ngfftprc(1) ; n2=this%ngfftprc(2) ; n3=this%ngfftprc(3)
823 : :
824 : : ! FFT
825 : 90 : call fourdp(cplex, vec_g, vec_r(:, 1), -1, mpi_enreg, this%nfftprc, 1, this%ngfftprc, 0)
826 : :
827 : 90 : ispden = 1
828 [ + + ]: 303750 : do ifft = 2, this%nfftprc
829 [ + + + + : 6073200 : g_cart_2 = norm2(two_pi * matmul(this%gprimd, get_g_vector(ifft, this%ngfftprc)))**2
+ + + - +
+ + + +
+ ]
830 [ + + ]: 911070 : vec_g(:, ifft, ispden) = (2*two_pi/g_cart_2) * vec_g(:, ifft, ispden)
831 : : end do
832 : :
833 : : ! Set contribution of unbalanced components to zero.
834 : 90 : call zerosym(vec_g(:, :, 1), 2, n1, n2, n3)
835 : :
836 : : ! iFFT
837 : 90 : call fourdp(cplex, vec_g, vec_r(:, 1), 1, mpi_enreg, this%nfftprc, 1, this%ngfftprc, 0)
838 : :
839 [ + + ]: 180 : do ispden = 2, dtset%nspden
840 [ + + ]: 303930 : vec_r(:, ispden) = 0
841 : : end do
842 : :
843 : 90 : end subroutine apply_vc
844 : :
845 : : !****f* m_precon/apply_kxc
846 : : !! NAME
847 : : !! apply_kxc
848 : : !!
849 : : !! FUNCTION
850 : : !! Apply the exchange and correlation kernel Kxc to a vector (in real space).
851 : : !!
852 : : !! INPUTS
853 : : !! dtset = All input variables for this dataset.
854 : : !! mpi_enreg = Informations about MPI parallelization.
855 : : !! vec_r (nfftprc, nspden) = Vector (in real space) to which the exchange and correlation kernel Kxc is applied.
856 : : !! When nspden > 1 vec_r is in the default Abinit spin-basis.
857 : : !!
858 : : !! OUTPUTS
859 : : !! Kxc_vec_r (nfftprc, nspden) = Resulting vector (in real space) containing the application of Kxc to vec_r.
860 : : !! When nspden > 1 Kxc_vec_r is in the Pauli-basis.
861 : : !!
862 : : !! SOURCE
863 : 55 : subroutine apply_kxc(this, dtset, mpi_enreg, vec_r, Kxc_vec_r)
864 : : !Arguments ------------------------------------
865 : : class(precon_object), intent(in) :: this
866 : : !scalars
867 : : type(dataset_type),intent(in) :: dtset
868 : : type(MPI_type),intent(in) :: mpi_enreg
869 : : !arrays
870 : : real(dp), intent(in) :: vec_r(this%nfftprc, dtset%nspden)
871 : : real(dp), intent(inout) :: Kxc_vec_r(this%nfftprc, dtset%nspden)
872 : :
873 : : !Local variables-------------------------------
874 : : !scalars
875 : : integer :: cplex, n3xccc, nhatdim, nhat1dim, nhat1grdim, nkxc, option, optnc, usexcnhat
876 : : logical :: non_magnetic_xc
877 : : !arrays
878 : 55 : real(dp), allocatable :: vec_r_default(:, :)
879 : 55 : real(dp), allocatable :: nhat(:, :), nhat1(:, :), nhat1gr(:, :, :)
880 : : real(dp) :: dummy_xccc3d1(0), qphon(3)
881 : :
882 : : ! *************************************************************************
883 : :
884 [ - + ]: 55 : if (size(this%kxc, 1) /= this%nfftprc) then
885 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): size(kxc, 1) /= nfftprc")
886 : : end if
887 : :
888 : : !Applying Kxc :
889 : 55 : cplex = 1 ! Input vector is real in real (direct) space.
890 : 55 : non_magnetic_xc = .false.
891 : 55 : nkxc = size(this%kxc, 2)
892 : :
893 : 55 : usexcnhat = 0 !
894 : 55 : nhat1dim = 0 !
895 [ - + + - : 110 : ABI_MALLOC(nhat1, (cplex*this%nfftprc, dtset%nspden*nhat1dim)) ! PAW
- + - + ]
896 : 55 : nhat1grdim = 0 !
897 [ - + + - : 165 : ABI_MALLOC(nhat1gr, (cplex*this%nfftprc, dtset%nspden, 3*nhat1grdim)) !
- + + - -
+ - + ]
898 : :
899 : 55 : option = 2 ! Treats only density change (no core_correction)
900 : 55 : n3xccc = 0 ! -> Core-correction set to 0.
901 : 55 : qphon = 0.0_dp ! phonon vector
902 : :
903 [ - + ]: 55 : if (dtset%nspden==1) then
904 : : call dfpt_mkvxc(cplex, dtset%ixc ,this%kxc, mpi_enreg, this%nfftprc, this%ngfftprc, nhat1, nhat1dim, &
905 : : & nhat1gr, nhat1grdim, nkxc, non_magnetic_xc, dtset%nspden, n3xccc, option, &
906 [ # # # # : 0 : & qphon, vec_r, this%rprimd, usexcnhat, Kxc_vec_r, dummy_xccc3d1)
# # # # #
# ]
907 : :
908 [ + - ]: 55 : else if (dtset%nspden==2) then
909 : : ! Basis change to the default Abinit spin-basis for densities in case
910 [ - + + - : 220 : ABI_MALLOC(vec_r_default, ((this%nfftprc), dtset%nspden))
- + + - +
- + - - +
- + ]
911 [ + - - + : 371470 : vec_r_default = vec_r
- - + + +
+ ]
912 : 55 : call from_pauli(1, vec_r_default)
913 : : call dfpt_mkvxc(cplex, dtset%ixc ,this%kxc, mpi_enreg, this%nfftprc, this%ngfftprc, nhat1, nhat1dim, &
914 : : & nhat1gr, nhat1grdim, nkxc, non_magnetic_xc, dtset%nspden, n3xccc, option, &
915 [ + - - - : 55 : & qphon, vec_r_default, this%rprimd, usexcnhat, Kxc_vec_r, dummy_xccc3d1)
- - - - -
+ ]
916 [ - + ]: 55 : ABI_FREE(vec_r_default)
917 : :
918 [ # # ]: 0 : else if (dtset%nspden==4) then
919 : : ! In non-collinear spin, the default Abinit spin-basis is the pauli basis. No basis change needed.
920 : 0 : nhatdim = 0
921 [ # # # # : 0 : ABI_MALLOC(nhat, (this%nfftprc, dtset%nspden*nhatdim)) !
# # # # ]
922 : 0 : optnc = 1 ! Compute the whole 2x2 Vres matrix
923 : : call dfpt_mkvxc_noncoll(cplex, dtset%ixc ,this%kxc, mpi_enreg, this%nfftprc, this%ngfftprc, nhat, nhatdim, &
924 : : & nhat1, nhat1dim, nhat1gr, nhat1grdim, nkxc, non_magnetic_xc, dtset%nspden, &
925 : : & n3xccc, optnc, option, qphon, this%rhor, vec_r, this%rprimd, usexcnhat, &
926 [ # # # # : 0 : & this%vxc, Kxc_vec_r, dummy_xccc3d1)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
927 [ # # ]: 0 : ABI_FREE(nhat)
928 : : end if
929 : :
930 [ - + ]: 55 : ABI_FREE(nhat1)
931 [ - + ]: 55 : ABI_FREE(nhat1gr)
932 : :
933 : 55 : call to_pauli(0, Kxc_vec_r)
934 : :
935 [ - + ]: 55 : end subroutine apply_kxc
936 : :
937 : : !****f* m_precon/apply_kernel
938 : : !! NAME
939 : : !! apply_kernel
940 : : !!
941 : : !! FUNCTION
942 : : !! Apply the kernel vc or (vc + Kxc) depending in iprcel to a vector (in place).
943 : : !!
944 : : !! INPUTS
945 : : !! dtset = All input variables for this dataset.
946 : : !! mpi_enreg = Informations about MPI parallelization.
947 : : !!
948 : : !! SIDE EFFECTS
949 : : !! vec_r (nfftprc, nspden) = Vector (in direct space) to which the kernel is applied (in place).
950 : : !! When nspden > 1 vec_r is in the default Abinit spin-basis.
951 : : !!
952 : : !! SOURCE
953 : 0 : subroutine apply_kernel(this, dtset, mpi_enreg, vec_r)
954 : : !Arguments ------------------------------------
955 : : class(precon_object), intent(inout) :: this
956 : : !scalars
957 : : type(dataset_type),intent(in) :: dtset
958 : : type(MPI_type),intent(in) :: mpi_enreg
959 : : !arrays
960 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
961 : :
962 : : !Local variables-------------------------------
963 : 0 : real(dp), allocatable :: Kxc_vec_r(:, :)
964 : :
965 : : ! *************************************************************************
966 : :
967 : : ! RPA : LDOS/Kerker model - only vc
968 [ # # ]: 0 : if (.not. this%use_kxc) then
969 : :
970 : 0 : call apply_vc(this, dtset, mpi_enreg, vec_r) ! Apply vc in place
971 : :
972 : : ! No RPA : vc and Kxc
973 : : else
974 : :
975 : : ! Apply Kxc
976 [ # # # # : 0 : ABI_MALLOC(Kxc_vec_r, (this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
977 : 0 : call apply_Kxc(this, dtset, mpi_enreg, vec_r, Kxc_vec_r)
978 : :
979 : : ! Apply vc in place
980 : 0 : call apply_vc(this, dtset, mpi_enreg, vec_r) ! Apply vc in place
981 : :
982 : : ! Add Kxc_vec_r to vec_r
983 [ # # # # ]: 0 : vec_r = vec_r + Kxc_vec_r
984 [ # # ]: 0 : ABI_FREE(Kxc_vec_r)
985 : :
986 : : end if
987 : :
988 : 0 : end subroutine apply_kernel
989 : :
990 : : !****f* m_precon/derivative_occ
991 : : !! NAME
992 : : !! derivative_occ
993 : : !!
994 : : !! FUNCTION
995 : : !! Compute the derivative of the occupation (f) of the band corresponding to eigenval
996 : : !! with respect to the fermie temperature.
997 : : !! f = integral_((eigenval - fermie)/tsmear)^infty delta(t) dt
998 : : !! f' = -1/tsmear * delta((eigenval - fermie)/tsmear)
999 : : !!
1000 : : !! INPUTS
1001 : : !! occopt = option for occupancies, determines delta
1002 : : !! eigenval = eigenvalue
1003 : : !! fermie = fermi energie
1004 : : !! tsmear = smearing temperature
1005 : : !!
1006 : : !! OUTPUT
1007 : : !! fprim = occupation derivative
1008 : : !!
1009 : : !! SOURCE
1010 : 11898 : function derivative_occ(occopt, eigenval, fermie, tsmear) result(fprim)
1011 : :
1012 : : !Arguments ------------------------------------
1013 : : !scalars
1014 : : real(dp), intent(in) :: eigenval, fermie, tsmear
1015 : : integer, intent(in) :: occopt
1016 : :
1017 : : !Local variables-------------------------------
1018 : : !scalars
1019 : : real(dp) :: x, delta, a
1020 : :
1021 : : !Returned variable-------------------------------
1022 : : real(dp) :: fprim
1023 : :
1024 : : ! *************************************************************************
1025 : :
1026 : 11898 : x = (eigenval - fermie)/tsmear
1027 : :
1028 [ - + ]: 11898 : if (occopt<=2) then
1029 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): Non-metallic occupation.")
1030 : : else if (occopt==3) then
1031 : : !Fermi-Dirac smearing
1032 : 11898 : delta = exp(-abs(x))/(1+exp(-abs(x)))**2 !To avoid overflow of exp.
1033 : : else if (occopt==4) then
1034 : : !Cold Smearing
1035 : 0 : a = -0.5634
1036 : 0 : delta = (1.5+x*(-1.5*a+x*(-1.0+a*x)))*exp(-x**2)/sqrt(pi)
1037 : : else if (occopt==5) then
1038 : : !Cold Smearing
1039 : 0 : a = -0.8165
1040 : 0 : delta = (1.5+x*(-1.5*a+x*(-1.0+a*x)))*exp(-x**2)/sqrt(pi)
1041 : : else if (occopt==6) then
1042 : : !Smering of Methfessel and Paxton
1043 : 0 : a = 0.0
1044 : 0 : delta = (1.5+x*(-1.5*a+x*(-1.0+a*x)))*exp(-x**2)/sqrt(pi)
1045 : : else if (occopt==7) then
1046 : : !Gaussian smearing
1047 : 0 : delta = exp(-x**2)/sqrt(pi)
1048 : : else if (occopt==8) then
1049 : : !Uniform smearing
1050 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): preconditioner needs a smooth smearing function.")
1051 : : else if (occopt==9) then
1052 : : !Fermi-Dirac occupation is enforced with two distinct quasi-Fermi levels
1053 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): preconditioner not implemented for this smearing function.")
1054 : : end if
1055 : :
1056 : 11898 : fprim = -1/tsmear * delta
1057 : :
1058 : 11898 : end function derivative_occ
1059 : :
1060 : : !****f* m_precon/compute_weighted_density
1061 : : !! NAME
1062 : : !! compute_weighted_density
1063 : : !!
1064 : : !! FUNCTION
1065 : : !! Wrapper for mkrho, symrhg and PAW :
1066 : : !! Compute a density-like quantity where the occupation are replaced by some weights
1067 : : !! w_rho = sum_i weight_i |psi_i|^2 .
1068 : : !! w_rho that has the same size as the preconditioned density/potential.
1069 : : !!
1070 : : !! INPUTS
1071 : : !! dtset = All input variables for this dataset.
1072 : : !! mpi_enreg = Information about MPI parallelization.
1073 : : !! weights = Weights that replace the occupations in the computation of density.
1074 : : !!
1075 : : !! OUTPUT
1076 : : !! w_rhor = "Weighted density" in real space, in the Pauli basis.
1077 : : !!
1078 : : !! SOURCE
1079 [ - + ]: 18 : subroutine compute_weighted_density(this, dtset, mpi_enreg, weights, w_rhor)
1080 : :
1081 : : !Arguments ------------------------------------
1082 : : !scalars
1083 : : class(precon_object), intent(in) :: this
1084 : : type(dataset_type), intent(in) :: dtset
1085 : : type(MPI_type), intent(in) :: mpi_enreg
1086 : : !arrays
1087 : : real(dp), intent(in) :: weights(:)
1088 : : real(dp), intent(out) :: w_rhor(this%nfftprc, dtset%nspden)
1089 : :
1090 : : !Local variables-------------------------------
1091 : : !scalars
1092 [ - + - + : 54 : type(pawrhoij_type) :: pawrhoij(mpi_enreg%my_natom*this%psps%usepaw)
- + - - -
- - - - -
- - - - ]
1093 : : integer :: dummy_int, mband_cprj, my_nspinor, mcprj_tmp
1094 : : integer :: mcg, cplex, cplex_rhoij
1095 : : real(dp) :: compch_fft
1096 : : integer :: optin, optout, optgrid
1097 : : !arrays
1098 : : real(dp) :: qphon(3)
1099 : 18 : real(dp), allocatable :: w_rhowfg(:, :), w_rhowfr(:, :)
1100 : 18 : type(pawcprj_type), allocatable :: cprj_tmp(:,:)
1101 : 18 : type(paw_dmft_type) :: dummy_paw_dmft
1102 : : type(wvl_wf_type) :: dummy_wvl_wfs
1103 : : type(wvl_denspot_type) :: dummy_wvl_den
1104 : : real(dp) :: dummy_ylmgr(0, 0, 0)
1105 : 18 : real(dp), allocatable :: dummy_rhog(:, :), dummy_rhogf(:, :)
1106 : :
1107 : : ! *************************************************************************
1108 : :
1109 [ + - ]: 18 : if (this%psps%usepaw==0) then
1110 [ - + + - : 72 : ABI_MALLOC(w_rhowfr, (dtset%nfft, dtset%nspden))
- + + - +
- + - - +
- + ]
1111 [ - + + - : 54 : ABI_MALLOC(w_rhowfg, (2, dtset%nfft))
+ - + - -
+ - + ]
1112 : : else
1113 [ # # # # : 0 : ABI_MALLOC(w_rhowfr, (this%pawfgr%nfftc, dtset%nspden))
# # # # #
# # # # #
# # ]
1114 [ # # # # : 0 : ABI_MALLOC(w_rhowfg, (2, this%pawfgr%nfftc))
# # # # #
# # # ]
1115 : : end if
1116 : : !w_rhowfr = zero
1117 : : !w_rhowfg = zero
1118 : :
1119 : : ! Compute the weighted density (w_rhor) using mkrho with weights in place of the occupations.
1120 [ + + ]: 54 : mcg = size(this%cg)
1121 : 18 : dummy_paw_dmft%use_dmft = 0
1122 : 18 : dummy_paw_dmft%use_sc_dmft = 0
1123 : : call mkrho(this%cg, dtset, this%gprimd, this%irrzon, this%kg, mcg, mpi_enreg, this%npwarr, weights, &
1124 [ + - - - : 18 : & dummy_paw_dmft, this%phnons, w_rhowfg, w_rhowfr, this%rprimd, 0, this%ucvol, dummy_wvl_den, dummy_wvl_wfs, option=0, printout=.false.)
- - - - +
- - - - -
- - - - +
- - - - -
- - + - -
- - - - +
- - - - +
- - - - -
- - - - -
+ - + - +
- + - + -
+ ]
1125 : : ! symrhg already called in mkrho
1126 : :
1127 [ + - ]: 18 : if (this%psps%usepaw==0) then
1128 : : ! In NC : the weighted density is directly w_rhowfr.
1129 [ + - ]: 18 : if (this%nfftprc == dtset%nfft) then
1130 [ + + + + ]: 121554 : w_rhor = w_rhowfr
1131 : : else
1132 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): nfftprc /= nfft in Norm-conserving not implemented.")
1133 : : end if
1134 : : else
1135 : : ! In PAW :
1136 : : ! First option : Add rhoij terms to w_rhowfr and transfer to fine grid. -UNUSED-
1137 [ # # # # ]: 0 : if (this%use_paw_rhoij .and. this%nfftprc == this%pawfgr%nfft) then
1138 : :
1139 : : !Compute the rhoij equivalent for the weighted density.
1140 : : ! Sum_{n,k} {weight(n,k)*<Cnk|p_i><p_j|Cnk>}.
1141 : :
1142 : 0 : my_nspinor = max(1, dtset%nspinor/mpi_enreg%nproc_spinor)
1143 : 0 : mband_cprj = dtset%mband / mpi_enreg%nproc_band
1144 : :
1145 : : !Initialize pawrhoij
1146 : 0 : cplex_rhoij = 1
1147 : : call pawrhoij_alloc(pawrhoij, cplex_rhoij, dtset%nspden, dtset%nspinor, &
1148 : 0 : & dtset%nsppol, dtset%typat, pawtab=this%pawtab)
1149 : :
1150 : : !Compute pawrhoij
1151 [ # # ]: 0 : if (this%usecprj == 1) then ! cprj is saved in memory
1152 : : call pawmkrhoij(this%atindx, this%atindx1, this%cprj, this%dimcprj, dtset%istwfk, dtset%kptopt, dtset%mband,&
1153 : : & mband_cprj, this%mcprj, dtset%mkmem, mpi_enreg, dtset%natom, dtset%nband, dtset%nkpt, dtset%nspden, &
1154 : : & dtset%nspinor, dtset%nsppol, weights, dtset%paral_kgb, dummy_paw_dmft, pawrhoij, this%unpaw, &
1155 [ # # # # : 0 : & dtset%usewvl, dtset%wtk)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
1156 : : else ! cprj is computed on the fly
1157 : 0 : mcprj_tmp = my_nspinor * mband_cprj * dtset%mkmem * dtset%nsppol
1158 [ # # # # : 0 : ABI_MALLOC(cprj_tmp, (dtset%natom, mcprj_tmp))
# # # # #
# # # # #
# # # # #
# ]
1159 : 0 : call pawcprj_alloc(cprj_tmp, 0, this%dimcprj)
1160 : : call ctocprj(this%atindx, this%cg, 1, cprj_tmp, this%gmet, this%gprimd, 0, 0, 0, dtset%istwfk, this%kg, &
1161 : : & dtset%kptns, mcg, mcprj_tmp, dtset%mgfft, dtset%mkmem, mpi_enreg, this%psps%mpsang, dtset%mpw, &
1162 : : & dtset%natom, this%nattyp, dtset%nband, dtset%natom, dtset%ngfft, dtset%nkpt, dtset%nloalg, &
1163 : : & this%npwarr, dtset%nspinor, dtset%nsppol, dtset%nsppol, dtset%ntypat, dtset%paral_kgb, this%ph1d, &
1164 [ # # # # : 0 : & this%psps, this%rmet, dtset%typat, this%ucvol, this%unpaw, this%xred, this%ylm, dummy_ylmgr)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
1165 : : call pawmkrhoij(this%atindx, this%atindx1, cprj_tmp, this%dimcprj, dtset%istwfk, dtset%kptopt, &
1166 : : & dtset%mband, mband_cprj, mcprj_tmp, dtset%mkmem, mpi_enreg, dtset%natom, dtset%nband, dtset%nkpt, &
1167 : : & dtset%nspden, dtset%nspinor, dtset%nsppol, weights, dtset%paral_kgb, dummy_paw_dmft, pawrhoij, &
1168 [ # # # # : 0 : & this%unpaw, dtset%usewvl, dtset%wtk)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
1169 : 0 : call pawcprj_free(cprj_tmp)
1170 [ # # # # : 0 : ABI_FREE(cprj_tmp)
# # # # #
# ]
1171 : : end if
1172 : :
1173 : : !Compute the total weighted density (adding PAW-correction).
1174 : 0 : cplex = 1
1175 : 0 : dummy_int=0
1176 : 0 : qphon = 0
1177 : : call pawmkrho(1, compch_fft, cplex, this%gprimd, dummy_int, this%indsym, dummy_int, mpi_enreg, &
1178 : : & mpi_enreg%my_natom, dtset%natom, dtset%nspden, dtset%nsym, dtset%ntypat, dtset%paral_kgb, this%pawang, &
1179 : : & this%pawfgr, this%pawfgrtab, dtset%pawprtvol, pawrhoij, pawrhoij, this%pawtab, qphon, w_rhowfg, &
1180 [ # # # # : 0 : & w_rhowfr, w_rhor, this%rprimd, dtset%symafm, this%symrec, dtset%typat, this%ucvol, dtset%usewvl, this%xred)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1181 : :
1182 : 0 : call pawrhoij_free(pawrhoij)
1183 : :
1184 : : ! Second option : Transfer density from coarse to fine grid without rhoij corrections.
1185 [ # # ]: 0 : elseif (this%nfftprc == this%pawfgr%nfft) then
1186 : : !Transfering the weighted density to the fine (PAW) grid, no rhoij correction added.
1187 : 0 : cplex = 1
1188 : 0 : optgrid = 1 ! coarse to fine
1189 : 0 : optin = 0 ! real space
1190 : 0 : optout = 0 !
1191 [ # # # # : 0 : ABI_MALLOC(dummy_rhog, (2, this%pawfgr%nfftc))
# # # # #
# # # ]
1192 [ # # # # : 0 : ABI_MALLOC(dummy_rhogf, (2, this%pawfgr%nfft))
# # # # #
# # # ]
1193 : : call transgrid(cplex, mpi_enreg, dtset%nspden, optgrid, optin, optout, dtset%paral_kgb, this%pawfgr, &
1194 : 0 : & dummy_rhog, dummy_rhogf, w_rhowfr, w_rhor)
1195 [ # # ]: 0 : ABI_FREE(dummy_rhog)
1196 [ # # ]: 0 : ABI_FREE(dummy_rhogf)
1197 : : !call symrhg(1, this%gprimd, this%irrzon, mpi_enreg, this%nfftprc, ?nfftot, dtset%ngfft, 1, dtset%nsppol, dtset%nsym, &
1198 : : !this%phnons, rhog, rhor, this%rprimd, dtset%symafm, dtset%symrel, dtset%tnons)
1199 : : else
1200 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): nfftprc /= pawfgr%nfft in PAW not implemented.")
1201 : : end if
1202 : :
1203 : : end if
1204 : :
1205 : : !With collinear spins the weighted density is not returned in the Pauli (tot/spin) basis by mkrho.
1206 [ + - ]: 18 : if (dtset%nspden == 2) then
1207 : : !spin = 2up - tot
1208 [ + + ]: 60768 : w_rhor(:, 2) = 2*w_rhor(:, 2) - w_rhor(:, 1)
1209 : : end if
1210 : :
1211 [ - + ]: 18 : ABI_FREE(w_rhowfr)
1212 [ - + ]: 18 : ABI_FREE(w_rhowfg)
1213 : :
1214 [ - + - + : 18 : end subroutine compute_weighted_density
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - + -
+ - + - +
- + - - -
- - - - -
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - - - -
- - ]
1215 : :
1216 : : !****f* m_precon/compute_ldos
1217 : : !! NAME
1218 : : !! compute_ldos
1219 : : !!
1220 : : !! FUNCTION
1221 : : !! Compute the local density of states defined as
1222 : : !! ldos = sum_nk f'_nk |u_nk|^2 .
1223 : : !! where f'_nk is the derivative of the occupation (nk) with respect to the fermi energie.
1224 : : !! When 'nspden'>1, the ldos is returned in the Pauli-basis.
1225 : : !!
1226 : : !! INPUTS
1227 : : !! dtset = all input variables for this dataset
1228 : : !! mpi_enreg = informations about MPI parallelization
1229 : : !!
1230 : : !! OUTPUT
1231 : : !! ldos = local density of state
1232 : : !!
1233 : : !! SOURCE
1234 [ - + ]: 18 : subroutine compute_ldos(this, dtset, mpi_enreg, ldos)
1235 : :
1236 : : !Arguments ------------------------------------
1237 : : !scalars
1238 : : !scalars
1239 : : class(precon_object), intent(in) :: this
1240 : : type(dataset_type), intent(in) :: dtset
1241 : : type(MPI_type), intent(in) :: mpi_enreg
1242 : : !arrays
1243 : : real(dp), intent(out) :: ldos(:, :)
1244 : :
1245 : : !Local variables-------------------------------
1246 : : !scalars
1247 : : integer :: maxocc, i_eigen
1248 : : !integer :: ikpt, iband, isppol, nband_k, i_eigen
1249 : : !arrays
1250 : 18 : real(dp), allocatable :: ldos_weights(:)
1251 : :
1252 : : ! *************************************************************************
1253 : :
1254 : : !compute weights
1255 [ - + + - : 54 : ABI_MALLOC(ldos_weights, (dtset%mband*dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
1256 : 18 : maxocc = two / (dtset%nsppol * dtset%nspinor) !Maximum number of occupations (1 or 2)
1257 [ + + ]: 1170 : ldos_weights = 0
1258 : :
1259 [ + + ]: 1170 : do i_eigen = 1, dtset%mband*dtset%nkpt*dtset%nsppol
1260 : 1170 : ldos_weights(i_eigen) = -derivative_occ(dtset%occopt, this%eigen(i_eigen), this%fermie, dtset%tsmear) * maxocc
1261 : : end do
1262 : :
1263 : : !Compute ldos using mkrho with ldos_weights in place of the occupations
1264 [ - + - - : 18 : call compute_weighted_density(this, dtset, mpi_enreg, ldos_weights, ldos)
- + - - -
- ]
1265 [ - + ]: 18 : ABI_FREE(ldos_weights)
1266 : :
1267 : 18 : end subroutine compute_ldos
1268 : :
1269 : : !****f* m_precon/apply_chi0_dfermie
1270 : : !! NAME
1271 : : !! apply_chi0_dfermie
1272 : : !!
1273 : : !! FUNCTION
1274 : : !!
1275 : : !!
1276 : : !! INPUTS
1277 : : !! dtset = All input variables for this dataset.
1278 : : !! mpi_enreg = Information about MPI parallelization.
1279 : : !!
1280 : : !! SIDE EFFECTS
1281 : : !! vec_r (nfftprc, nspden) = Vector (in real space) to which the model chi0 operator is applied (in place).
1282 : : !! When nspden > 1 vec_r is in the Pauli spin-basis.
1283 : : !!
1284 : : !! SOURCE
1285 : 90 : subroutine apply_chi0_dfermie(this, dtset, vec_r)
1286 : :
1287 : : !Arguments ------------------------------------
1288 : : class(precon_object), intent(in) :: this
1289 : : !scalars
1290 : : type(dataset_type),intent(in) :: dtset
1291 : : !arrays
1292 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
1293 : :
1294 : : !Local variables-------------------------------
1295 : : integer :: ispden, jspden
1296 : : real(dp) :: delta_fermie
1297 : :
1298 : : ! *************************************************************************
1299 : :
1300 : : ! Precompute the dot product between the ldos and vec for each spin coordinate
1301 : 90 : delta_fermie = zero
1302 [ + + ]: 270 : do jspden = 1, dtset%nspden
1303 [ + + ]: 607770 : delta_fermie = delta_fermie + 1/this%tdos * dot_product(this%ldos(:, jspden), vec_r(:, jspden)) * this%dvol
1304 : : end do
1305 [ + + ]: 270 : do ispden = 1, dtset%nspden
1306 [ + + ]: 607770 : vec_r(:, ispden) = delta_fermie * this%ldos(:, ispden)
1307 : : end do
1308 : :
1309 : 90 : end subroutine apply_chi0_dfermie
1310 : :
1311 : : !****f* m_precon/apply_chi0_ldos
1312 : : !! NAME
1313 : : !! apply_chi0_ldos
1314 : : !!
1315 : : !! FUNCTION
1316 : : !! Apply the ldos model chi0 operator to the vector vec_r (in place) in the Pauli basis.
1317 : : !!
1318 : : !! INPUTS
1319 : : !! dtset =
1320 : : !!
1321 : : !! SIDE EFFECTS
1322 : : !! vec_r (nfftprc, nspden) = Vector (in direct space) to which the model chi0 operator is applied (in place).
1323 : : !! When nspden > 1 vec_r is in the Pauli basis.
1324 : : !!
1325 : : !! SOURCE
1326 : 90 : subroutine apply_chi0_ldos(this, dtset, vec_r)
1327 : :
1328 : : !Arguments ------------------------------------
1329 : : class(precon_object), intent(in) :: this
1330 : : type(dataset_type),intent(in) :: dtset
1331 : : !arrays
1332 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
1333 : :
1334 : : !Local variables-------------------------------
1335 : : !scalars
1336 : : integer :: ispden
1337 : : !arrays
1338 : 90 : real(dp), allocatable :: work_r(:, :)
1339 : :
1340 : : ! *************************************************************************
1341 : :
1342 [ - + ]: 90 : if (abs(this%tdos) > epsilon(this%tdos)) then !Checking that tdos is not 0.
1343 [ - + + - : 360 : ABI_MALLOC(work_r, (this%nfftprc, dtset%nspden))
- + + - +
- + - - +
+ - ]
1344 : :
1345 : : !1) chi0(v)(r)_1 = -sum_ispden ldos_ispden(r)*v_ispden(r).
1346 [ + + ]: 303840 : work_r(:, 1) = 0
1347 [ + + ]: 270 : do ispden = 1, dtset%nspden
1348 [ + + ]: 607770 : work_r(:, 1) = work_r(:, 1) - this%ldos(:, ispden)*vec_r(:, ispden)
1349 : : end do
1350 : : !2) chi0(v)(r)_ispden = -ldos_ispden(r)*v_1(r) for ispden>1.
1351 [ + + ]: 180 : do ispden = 2, dtset%nspden
1352 [ + + ]: 303930 : work_r(:, ispden) = -this%ldos(:, ispden)*vec_r(:, 1)
1353 : : end do
1354 : : !3) Apply the part comming from the variations of the Fermi-level.
1355 : 90 : call apply_chi0_dfermie(this, dtset, vec_r)
1356 [ + + + + ]: 607770 : vec_r = work_r + vec_r
1357 : :
1358 [ - + ]: 90 : ABI_FREE(work_r)
1359 : : else
1360 [ # # # # ]: 0 : vec_r = 0
1361 : : end if
1362 : :
1363 : 90 : end subroutine apply_chi0_ldos
1364 : :
1365 : : !!***
1366 : : !!****f* ABINIT/apply_adjdielmat_ldos
1367 : : !! NAME
1368 : : !! apply_adjdielmat
1369 : : !!
1370 : : !! FUNCTION
1371 : : !! Apply the ldos- adjoint dielectric matrix I-chi0_ldos*vc to the density rho_r (given in the direct space).
1372 : : !!
1373 : : !! INPUTS
1374 : : !! dtset = All input variables for this dataset.
1375 : : !! mpi_enreg = Information about MPI parallelization.
1376 : : !! rho_r = Density vector (in direct space).
1377 : : !!
1378 : : !! OUTPUT
1379 : : !! adjdielmat_rho_r = adjdielmat * rho_r
1380 : : !!
1381 : : !! NOTES
1382 : : !!
1383 : : !! SOURCE
1384 : 90 : subroutine apply_adjdielmat_ldos(this, dtset, mpi_enreg, rho_r, adjdielmat_rho_r)
1385 : :
1386 : : !Arguments ------------------------------------
1387 : : class(precon_object) :: this
1388 : : !scalars
1389 : : type(dataset_type),intent(in) :: dtset
1390 : : type(MPI_type),intent(in) :: mpi_enreg
1391 : : !arrays
1392 : : real(dp), intent(in) :: rho_r(this%nfftprc, dtset%nspden)
1393 : : real(dp), intent(inout) :: adjdielmat_rho_r(this%nfftprc, dtset%nspden)
1394 : :
1395 : : ! *************************************************************************
1396 : :
1397 [ + + + + ]: 607770 : adjdielmat_rho_r = rho_r
1398 : : !1) Apply vc (in the Pauli basis)
1399 : 90 : call apply_vc(this, dtset, mpi_enreg, adjdielmat_rho_r)
1400 : : !2) Apply chi0_ldos (in the Pauli basis)
1401 : 90 : call apply_chi0_ldos(this, dtset, adjdielmat_rho_r)
1402 : : !3) adjdielmat_rho_r = rho_r - vc * chi0 * rho_r = adjdielmat * rho_r
1403 [ + + + + ]: 607770 : adjdielmat_rho_r = rho_r - adjdielmat_rho_r
1404 : :
1405 : 90 : end subroutine apply_adjdielmat_ldos
1406 : :
1407 : : !!***
1408 : : !!****f* ABINIT/apply_dielmat_ldos
1409 : : !! NAME
1410 : : !! apply_adjdielmat
1411 : : !!
1412 : : !! FUNCTION
1413 : : !! Apply the ldos- dielectric matrix I-vc*chi0_ldos to the potential v_r (given in the direct space).
1414 : : !!
1415 : : !! INPUTS
1416 : : !! dtset = All input variables for this dataset.
1417 : : !! mpi_enreg = Information about MPI parallelization.
1418 : : !! v_r = Density vector (in direct space).
1419 : : !!
1420 : : !! OUTPUT
1421 : : !! dielmat_v_r = dielmat * v_r
1422 : : !!
1423 : : !! NOTES
1424 : : !!
1425 : : !! SOURCE
1426 : 0 : subroutine apply_dielmat_ldos(this, dtset, mpi_enreg, v_r, dielmat_v_r)
1427 : :
1428 : : !Arguments ------------------------------------
1429 : : class(precon_object) :: this
1430 : : !scalars
1431 : : type(dataset_type),intent(in) :: dtset
1432 : : type(MPI_type),intent(in) :: mpi_enreg
1433 : : !arrays
1434 : : real(dp), intent(in) :: v_r(this%nfftprc, dtset%nspden)
1435 : : real(dp), intent(inout) :: dielmat_v_r(this%nfftprc, dtset%nspden)
1436 : :
1437 : : ! *************************************************************************
1438 : :
1439 [ # # # # ]: 0 : dielmat_v_r = v_r
1440 : : !1) Apply chi0_ldos (in the Pauli basis)
1441 : 0 : call apply_chi0_ldos(this, dtset, dielmat_v_r)
1442 : : !2) Apply vc (in the Pauli basis)
1443 : 0 : call apply_vc(this, dtset, mpi_enreg, dielmat_v_r)
1444 : : !3) dielmat_v_r = v_r - vc * chi0 * v_r = dielmat * v_r
1445 [ # # # # ]: 0 : dielmat_v_r = v_r - dielmat_v_r
1446 : :
1447 : 0 : end subroutine apply_dielmat_ldos
1448 : :
1449 : : !****f* m_precon/get_eigen_index
1450 : : !! NAME
1451 : : !! get_eigen_index
1452 : : !!
1453 : : !! FUNCTION
1454 : : !! Return the index of the eigenvalue corresponding to (iband, ikpt, isppol)
1455 : : !! in the flat 'eigen' array.
1456 : : !!
1457 : : !! INPUTS
1458 : : !! dtset = All input variables for this dataset.
1459 : : !! iband = Band index.
1460 : : !! ikpt = K-point index.
1461 : : !! isppol = Spin-polarization index.
1462 : : !!
1463 : : !! OUTPUT
1464 : : !! i_eigen = Index of (iband, ikpt, isppol) in the eigen array.
1465 : : !!
1466 : : !! SOURCE
1467 : 10746 : function get_eigen_index(dtset, iband, ikpt, isppol) result(i_eigen)
1468 : :
1469 : : !Arguments ------------------------------------
1470 : : !scalars
1471 : : type(dataset_type),intent(in) :: dtset
1472 : : integer, intent(in) :: iband, ikpt, isppol
1473 : :
1474 : : !Returned variable-------------------------------
1475 : : integer :: i_eigen
1476 : :
1477 : : ! *************************************************************************
1478 : :
1479 : 10746 : i_eigen = iband + (ikpt-1)*dtset%mband + (isppol-1)*dtset%mband*dtset%nkpt
1480 : :
1481 : : end function get_eigen_index
1482 : :
1483 : : !****f* m_precon/compute_cg_indices
1484 : : !! NAME
1485 : : !! compute_cg_indices
1486 : : !!
1487 : : !! FUNCTION
1488 : : !! Compute the index ranges of each wavefunction (iband, ikpt, isppol) in the
1489 : : !! flat 'cg' array. For nspinor=2, separate ranges are stored for the
1490 : : !! spin-up and spin-down spinor components.
1491 : : !!
1492 : : !! INPUTS
1493 : : !! dtset = All input variables for this dataset.
1494 : : !! mpi_enreg = Information about MPI parallelization.
1495 : : !! npwarr = Number of plane-waves at each k-point.
1496 : : !!
1497 : : !! OUTPUTS
1498 : : !! cg_indices(2*nspinor, mband, nkpt, nsppol) = Index ranges in the cg array.
1499 : : !! cg_indices(1, iband, ikpt, isppol) : start index of wavefunction (iband, ikpt, isppol)
1500 : : !! (spin-up spinor component if nspinor=2).
1501 : : !! cg_indices(2, iband, ikpt, isppol) : end index.
1502 : : !! cg_indices(3, iband, ikpt, isppol) : start index of the spin-down spinor component (nspinor=2 only).
1503 : : !! cg_indices(4, iband, ikpt, isppol) : end index of the spin-down spinor component (nspinor=2 only).
1504 : : !!
1505 : : !! SOURCE
1506 [ - + ]: 10 : subroutine compute_cg_indices(dtset, mpi_enreg, npwarr, cg_indices)
1507 : :
1508 : : !Arguments ------------------------------------
1509 : : type(dataset_type),intent(in) :: dtset
1510 : : type(MPI_type), intent(in) :: mpi_enreg
1511 : : integer, intent(in) :: npwarr(:)
1512 : : integer :: cg_indices(2*dtset%nspinor, dtset%mband, dtset%nkpt, dtset%nsppol)
1513 : : ! If nspinor=2 : cg_indices(1, iband, ikpt, isppol):cg_indices(2, iband, ikpt, isppol) is the range of the spin up
1514 : : ! cg_indices(3, iband, ikpt, isppol):cg_indices(4, iband, ikpt, isppol) is the range of the spin down
1515 : : ! for the band of indices (iband, ikpt, isppol).
1516 : :
1517 : : !Local variables ------------------------------
1518 : : integer :: iband, ikpt, isppol, i_cg
1519 : :
1520 : : ! *************************************************************************
1521 : :
1522 [ + + + + : 1990 : cg_indices = zero
+ + + + ]
1523 : 10 : i_cg = 1
1524 [ + + ]: 30 : do isppol =1, dtset%nsppol
1525 [ + + ]: 70 : do ikpt = 1, dtset%nkpt
1526 [ + + ]: 700 : do iband = 1, dtset%nband(ikpt)
1527 [ + - ]: 640 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, iband, iband, isppol, mpi_enreg%me_kpt)) then
1528 : : cycle
1529 : : end if
1530 : 640 : cg_indices(1, iband, ikpt, isppol) = i_cg
1531 : 640 : cg_indices(2, iband, ikpt, isppol) = cg_indices(1, iband, ikpt, isppol) + npwarr(ikpt) - 1
1532 : 640 : i_cg = cg_indices(2, iband, ikpt, isppol) + 1
1533 [ - + ]: 680 : if (dtset%nspinor==2) then
1534 : 0 : cg_indices(3, iband, ikpt, isppol) = i_cg
1535 : 0 : cg_indices(4, iband, ikpt, isppol) = cg_indices(3, iband, ikpt, isppol) + npwarr(ikpt) - 1
1536 : 0 : i_cg = cg_indices(4, iband, ikpt, isppol) + 1
1537 : : end if
1538 : : end do
1539 : : end do
1540 : : end do
1541 : :
1542 : 10 : end subroutine compute_cg_indices
1543 : :
1544 : : !****f* m_precon/compute_kg_indices
1545 : : !! NAME
1546 : : !! compute_kg_indices
1547 : : !!
1548 : : !! FUNCTION
1549 : : !! Compute the index ranges of the plane-wave coordinates of each k-point
1550 : : !! in the flat 'kg' array.
1551 : : !!
1552 : : !! INPUTS
1553 : : !! dtset = All input variables for this dataset.
1554 : : !! mpi_enreg = Information about MPI parallelization.
1555 : : !! npwarr = Number of plane-waves at each k-point.
1556 : : !!
1557 : : !! OUTPUTS
1558 : : !! kg_indices(2, nkpt) = Index ranges in the kg array.
1559 : : !! kg_indices(1, ikpt) : start index of k-point ikpt in the kg array.
1560 : : !! kg_indices(2, ikpt) : end index.
1561 : : !!
1562 : : !! SOURCE
1563 [ - + ]: 10 : subroutine compute_kg_indices(dtset, mpi_enreg, npwarr, kg_indices)
1564 : :
1565 : : !Arguments ------------------------------------
1566 : : type(dataset_type),intent(in) :: dtset
1567 : : type(MPI_type), intent(in) :: mpi_enreg
1568 : : integer, intent(in) :: npwarr(:)
1569 : : integer, intent(inout) :: kg_indices(2, dtset%nkpt)
1570 : : !Returned variable ----------------------------
1571 : : integer :: i_kg, ikpt, isppol
1572 : :
1573 : : ! *************************************************************************
1574 : :
1575 [ + + + + ]: 70 : kg_indices = zero
1576 [ + + ]: 30 : do isppol =1, dtset%nsppol
1577 : 20 : i_kg = 1
1578 [ + + ]: 70 : do ikpt = 1, dtset%nkpt
1579 [ - + ]: 40 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, dtset%nband(ikpt+(isppol-1)*dtset%nkpt), isppol, mpi_enreg%me_kpt)) then
1580 : : cycle
1581 : : end if
1582 : 40 : kg_indices(1, ikpt) = i_kg
1583 : 40 : kg_indices(2, ikpt) = kg_indices(1, ikpt) + npwarr(ikpt) - 1
1584 : 60 : i_kg = kg_indices(2, ikpt) + 1
1585 : : end do
1586 : : end do
1587 : :
1588 : 10 : end subroutine compute_kg_indices
1589 : :
1590 : : !****f* m_precon/transfer_grid
1591 : : !! NAME
1592 : : !! transfer_grid
1593 : : !!
1594 : : !! FUNCTION
1595 : : !! Wrapper for fftpac and transgrid (PAW).
1596 : : !! Transfer one spin component of a real-space density from the augmented
1597 : : !! wavefunction FFT grid to the preconditioning FFT grid.
1598 : : !! In norm-conserving calculations, the two grids are identical and fftpac is used.
1599 : : !! In PAW calculations, the density is first packed to the coarse grid with fftpac
1600 : : !! and then interpolated to the fine grid with transgrid.
1601 : : !!
1602 : : !! INPUTS
1603 : : !! dtset = All input variables for this dataset.
1604 : : !! mpi_enreg = Information about MPI parallelization.
1605 : : !! ispden = Spin component index to write into rho_r.
1606 : : !! rho_aug_r(n4, n5, n6) = Density on the augmented wavefunction FFT grid.
1607 : : !!
1608 : : !! SIDE EFFECTS
1609 : : !! rho_r(nfftprc, nspden) = On output, column ispden is filled with the
1610 : : !! density transferred to the preconditioning grid.
1611 : : !!
1612 : : !! SOURCE
1613 [ - + - + ]: 216 : subroutine transfer_grid(this, dtset, mpi_enreg, ispden, rho_aug_r, rho_r)
1614 : :
1615 : : !Arguments ------------------------------------
1616 : : class(precon_object), intent(inout) :: this
1617 : : !scalars
1618 : : type(dataset_type),intent(in) :: dtset
1619 : : type(MPI_type), intent(in) :: mpi_enreg
1620 : : integer :: ispden
1621 : : !arrays
1622 : : real(dp), intent(inout) :: rho_r(:, :)
1623 : : real(dp), intent(inout) :: rho_aug_r(:, :, :)
1624 : :
1625 : : !Local variables-------------------------------
1626 : : integer :: n1, n2, n3, n4, n5, n6
1627 : : integer :: cplex, optgrid, optin, optout
1628 : 216 : real(dp), allocatable :: rho_coarse_r(:, :)
1629 : 216 : real(dp), allocatable :: dummy_rhog(:, :), dummy_rhogf(:, :)
1630 : :
1631 : : ! *************************************************************************
1632 : :
1633 : 216 : n1 = dtset%ngfft(1)
1634 : 216 : n2 = dtset%ngfft(2)
1635 : 216 : n3 = dtset%ngfft(3)
1636 : 216 : n4 = dtset%ngfft(4)
1637 : 216 : n5 = dtset%ngfft(5)
1638 : 216 : n6 = dtset%ngfft(6)
1639 : :
1640 [ + - ]: 216 : if (this%psps%usepaw==0) then
1641 : : ! In NC, the preconditioning grid should be the density/potential grid.
1642 [ + - ]: 216 : if (this%nfftprc == n1*n2*n3) then
1643 [ - + - - : 216 : call fftpac(ispden, mpi_enreg, 1, n1, n2, n3, n4, n5, n6, dtset%ngfft, rho_r, rho_aug_r, 1)
- - - - -
+ - - - -
- - - - -
+ - - - -
- + - - -
- - - ]
1644 : : else
1645 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): nfftprc /= nfft in norm-conserving not implemented.")
1646 : : end if
1647 : : else
1648 : : ! In PAW, the preconditioning grid should be the fine grid.
1649 [ # # ]: 0 : if (this%nfftprc == this%pawfgr%nfft) then
1650 [ # # # # : 0 : ABI_MALLOC(rho_coarse_r, (dtset%nfft, 1))
# # # # #
# # # ]
1651 : : ! Augmented grid to coarse grid :
1652 [ # # # # : 0 : call fftpac(1, mpi_enreg, 1, n1, n2, n3, n4, n5, n6, dtset%ngfft, rho_coarse_r, rho_aug_r, 1)
# # # # #
# # # # #
# # # # ]
1653 : : ! Coarse grid to fine grid :
1654 : 0 : cplex = 1
1655 : 0 : optgrid = 1 ! coarse to fine
1656 : 0 : optin = 0 ! real space
1657 : 0 : optout = 0 !
1658 [ # # # # : 0 : ABI_MALLOC(dummy_rhog, (2, this%pawfgr%nfftc))
# # # # #
# # # ]
1659 [ # # # # : 0 : ABI_MALLOC(dummy_rhogf, (2, this%pawfgr%nfft))
# # # # #
# # # ]
1660 [ # # # # : 0 : call transgrid(cplex, mpi_enreg, 1, optgrid, optin, optout, dtset%paral_kgb, this%pawfgr, dummy_rhog, dummy_rhogf, rho_coarse_r, rho_r(:, ispden))
# # # # #
# ]
1661 [ # # ]: 0 : ABI_FREE(dummy_rhog)
1662 [ # # ]: 0 : ABI_FREE(dummy_rhogf)
1663 [ # # ]: 0 : ABI_FREE(rho_coarse_r)
1664 : : else
1665 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): nfftprc /= pawfgr%nfft in PAW not implemented.")
1666 : : end if
1667 : :
1668 : : end if
1669 : :
1670 : 216 : end subroutine transfer_grid
1671 : :
1672 : : ! Compute rho_i in collinear case without PAW corrections
1673 : : !****f* m_precon/compute_rhoi_coll
1674 : : !! NAME
1675 : : !! compute_rhoi_coll
1676 : : !!
1677 : : !! FUNCTION
1678 : : !! Compute the normalized orbital density
1679 : : !! rho_i(r) = |psi_i(r)|^2
1680 : : !! for a given band, k-point and spin channel in the collinear case.
1681 : : !! The density is transferred to the preconditioning grid and normalized.
1682 : : !!
1683 : : !! INPUTS
1684 : : !! dtset = All input variables for this dataset.
1685 : : !! mpi_enreg = Information about MPI parallelization.
1686 : : !! iband = Band index.
1687 : : !! ikpt = K-point index.
1688 : : !! isppol = Spin-polarization index.
1689 : : !!
1690 : : !! OUTPUTS
1691 : : !! rhoi_r(nfftprc,1) = Normalized orbital density on the preconditioning grid.
1692 : : !!
1693 : : !! SOURCE
1694 : 216 : subroutine compute_rhoi_coll(this, dtset, mpi_enreg, iband, ikpt, isppol, rhoi_r)
1695 : :
1696 : : !Arguments ------------------------------------
1697 : : class(precon_object), intent(inout) :: this
1698 : : !scalars
1699 : : type(dataset_type),intent(in) :: dtset
1700 : : type(MPI_type), intent(in) :: mpi_enreg
1701 : : integer, intent(in) :: isppol, ikpt, iband
1702 : : real(dp), intent(inout) :: rhoi_r(this%nfftprc, 1)
1703 : :
1704 : : !Local variables-------------------------------
1705 : : !scalars
1706 : : integer :: ndat, option, tim_fourwf
1707 : : integer :: i_cg(2), i_kg(2)
1708 : : integer :: n1, n2, n3, n4, n5, n6
1709 : : integer :: istwf_k, npw_k
1710 : : !arrays
1711 : 432 : integer :: gbound(2*dtset%mgfft+8,2)
1712 : 216 : integer, allocatable :: kg_k(:, :)
1713 : 216 : real(dp), allocatable :: rhoi_aug_r(:, :, :)
1714 : : !dummy arguments
1715 : : integer :: dummy_int
1716 : 432 : real(dp) :: dummy_fofgout(2, 0), dummy_fofrout(2, dtset%ngfft(4), dtset%ngfft(5), dtset%ngfft(6))
1717 : :
1718 : : ! *************************************************************************
1719 : :
1720 : 216 : n1 = dtset%ngfft(1)
1721 : 216 : n2 = dtset%ngfft(2)
1722 : 216 : n3 = dtset%ngfft(3)
1723 : 216 : n4 = dtset%ngfft(4)
1724 : 216 : n5 = dtset%ngfft(5)
1725 : 216 : n6 = dtset%ngfft(6)
1726 : :
1727 : : ! No spin or collinear spins - Wafefunctions have one spin component.
1728 [ + - ]: 216 : if (dtset%nspinor == 1) then
1729 : :
1730 : : ! 1) Compute orbital density in real space (augmented basis) :
1731 : :
1732 : : ! Input parameters for fourwf :
1733 : 216 : option = 1 ! Computes the density.
1734 : 216 : ndat = 1 ! Only one FFT.
1735 : 216 : tim_fourwf = 0
1736 [ - + + - : 1080 : ABI_MALLOC(rhoi_aug_r, (n4, n5, n6))
- + + - -
+ + - + -
+ - - + -
+ ]
1737 [ + + + + : 781056 : rhoi_aug_r = zero ! Initialization for fourwf (accumulation).
+ + ]
1738 : 216 : istwf_k = dtset%istwfk(ikpt) ! Option parameter that describes the storage of wfs at this kpt.
1739 : :
1740 [ - + - - ]: 216 : if (.not. (dtset%paral_kgb == 1 .and. dtset%npband > 1)) then
1741 : 216 : npw_k = this%npwarr(ikpt) ! Number of plane-wave at this kpt.
1742 [ - + + - : 648 : ABI_MALLOC(kg_k, (3, npw_k))
+ - + - -
+ - + ]
1743 [ + + ]: 648 : i_kg = this%kg_indices(:, ikpt)
1744 [ + - + - : 93344 : kg_k = this%kg(:, i_kg(1):i_kg(2)) ! Reduced plane-wave coordinate (k+G) of this kpt.
- + - - +
+ + + ]
1745 : 216 : call sphereboundary(gbound, istwf_k, kg_k, dtset%mgfft, npw_k)
1746 [ + + ]: 648 : i_cg = this%cg_indices(:, iband, ikpt, isppol)
1747 : : call fourwf(1, rhoi_aug_r, this%cg(:, i_cg(1):i_cg(2)), dummy_fofgout, dummy_fofrout, &
1748 : : & gbound, gbound, istwf_k, kg_k, kg_k, dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
1749 [ - + - - : 216 : & dummy_int, n4, n5, n6, option, tim_fourwf, one, one)
- - - - -
+ - - -
- ]
1750 : : else
1751 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): 'compute_rhoi_coll' should not be called with band parallelization.")
1752 : : end if
1753 [ - + ]: 216 : ABI_FREE(kg_k)
1754 : :
1755 : : ! 2) Transfer rhoi_aug_r defined on the augmented (wavefunction) fft-grid to the preconditioning fft-grid.
1756 : 216 : call transfer_grid(this, dtset, mpi_enreg, 1, rhoi_aug_r, rhoi_r)
1757 [ - + ]: 216 : ABI_FREE(rhoi_aug_r)
1758 : :
1759 : : !3) Normalize rhoi_r.
1760 [ + + + + ]: 1458216 : rhoi_r(:, 1) = rhoi_r(:, 1) / (sum(rhoi_r(:, 1)) * this%dvol) !Normalizing rho_ii_r.
1761 : :
1762 : : else
1763 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): compute_rhoi_coll called with non-collinear magnetism.")
1764 : : end if
1765 : :
1766 [ - + ]: 216 : end subroutine compute_rhoi_coll
1767 : :
1768 : : !****f* m_precon/build_non_coll_density
1769 : : !! NAME
1770 : : !! build_non_coll_density
1771 : : !!
1772 : : !! FUNCTION
1773 : : !! Construct the four Pauli-basis components of the orbital density
1774 : : !! associated with a non-collinear spinor wavefunction and normalize
1775 : : !! the resulting density.
1776 : : !!
1777 : : !! INPUTS
1778 : : !! dtset = All input variables for this dataset.
1779 : : !! mpi_enreg = Information about MPI parallelization.
1780 : : !! psi_r_up = Spin-up component of the wavefunction in real space.
1781 : : !! psi_r_down = Spin-down component of the wavefunction in real space.
1782 : : !!
1783 : : !! OUTPUTS
1784 : : !! rhoi_r(nfftprc,4) = Normalized orbital density in the Pauli basis.
1785 : : !!
1786 : : !! SOURCE
1787 [ # # # # ]: 0 : subroutine build_non_coll_density(this, dtset, mpi_enreg, psi_r_up, psi_r_down, rhoi_r)
1788 : : !Arguments ------------------------------------
1789 : : class(precon_object), intent(inout) :: this
1790 : : !scalars
1791 : : type(dataset_type),intent(in) :: dtset
1792 : : type(MPI_type), intent(in) :: mpi_enreg
1793 : : real(dp), intent(in) :: psi_r_up(:, :, :, :), psi_r_down(:, :, :, :)
1794 : : real(dp), intent(inout) :: rhoi_r(this%nfftprc, 4)
1795 : :
1796 : : !Local variables-------------------------------
1797 : : !scalars
1798 : : integer :: n4, n5, n6
1799 : : integer :: ispden
1800 : : real(dp) :: norm_tot
1801 : : !arrays
1802 : 0 : real(dp), allocatable :: rhoi_aug_r(:, :, :, :)
1803 : :
1804 : : ! *************************************************************************
1805 : :
1806 : 0 : n4 = dtset%ngfft(4)
1807 : 0 : n5 = dtset%ngfft(5)
1808 : 0 : n6 = dtset%ngfft(6)
1809 : :
1810 [ # # # # : 0 : ABI_MALLOC(rhoi_aug_r, (n4, n5, n6, 4))
# # # # #
# # # # #
# # # # #
# # # ]
1811 : 0 : ispden = 1 ! rho_sigma0(r) = |psi_up(r)|^2 + |psi_down(r)|^2
1812 [ # # # # : 0 : rhoi_aug_r(:, :, :, ispden) = psi_r_up(1, :, :, :)**2 + psi_r_up(2, :, :, :)**2 + psi_r_down(1, :, :, :)**2 + psi_r_down(2, :, :, :)**2
# # ]
1813 : : ispden = 2 ! rho_sigma1(r) = psi_up(r)* . psi_down(r) + psi_down(r)* . psi_up(r) = 2 Re(psi_up(r)*psi_down(r))
1814 : : ! (* = conjugate)
1815 [ # # # # : 0 : rhoi_aug_r(:, :, :, ispden) = 2*( psi_r_up(1, :, :, :)*psi_r_down(1, :, :, :) + psi_r_up(2, :, :, :)*psi_r_down(2, :, :, :) )
# # ]
1816 : 0 : ispden = 3 ! rho_sigma2(r) = i*(psi_down(r)* psi_up(r) - psi_up(r)* psi_down(r)) = 2 Im(psi_up(r)*psi_down(r))
1817 [ # # # # : 0 : rhoi_aug_r(:, :, :, ispden) = 2*( psi_r_up(2, :, :, :)*psi_r_down(1, :, :, :) - psi_r_up(1, :, :, :)*psi_r_down(2, :, :, :) )
# # ]
1818 : : ispden = 4 ! rho_sigma3(r) = |psi_up|^2 - |psi_down|^2
1819 [ # # # # : 0 : rhoi_aug_r(:, :, :, ispden) = psi_r_up(1, :, :, :)**2 + psi_r_up(2, :, :, :)**2 - psi_r_down(1, :, :, :)**2 - psi_r_down(2, :, :, :)**2
# # ]
1820 : :
1821 : : ! Change grid
1822 [ # # ]: 0 : do ispden = 1, 4
1823 : 0 : call transfer_grid(this, dtset, mpi_enreg, ispden, rhoi_aug_r(:, :, :, ispden), rhoi_r)
1824 : : end do
1825 : : ! TODO : here deal with cases where nspinor = 2 but nspden != 4 ...
1826 : :
1827 [ # # ]: 0 : ABI_FREE(rhoi_aug_r)
1828 : :
1829 : : !3) Normalize rhoi_r.
1830 [ # # ]: 0 : norm_tot = 0.5_dp * sum(rhoi_r(:, 1)) * this%dvol
1831 [ # # ]: 0 : do ispden = 1, 4
1832 [ # # ]: 0 : rhoi_r(:, ispden) = rhoi_r(:, ispden) / norm_tot !Normalizing rho_ii_r.
1833 : : end do
1834 : :
1835 : 0 : end subroutine build_non_coll_density
1836 : :
1837 : : !****f* m_precon/compute_rhoi_noncoll
1838 : : !! NAME
1839 : : !! compute_rhoi_noncoll
1840 : : !!
1841 : : !! FUNCTION
1842 : : !! Compute the normalized orbital density associated with a given
1843 : : !! band, k-point and spin channel in the non-collinear case.
1844 : : !! The density is returned in the Pauli basis on the preconditioning grid.
1845 : : !!
1846 : : !! INPUTS
1847 : : !! dtset = All input variables for this dataset.
1848 : : !! mpi_enreg = Information about MPI parallelization.
1849 : : !! iband = Band index.
1850 : : !! ikpt = K-point index.
1851 : : !! isppol = Spin-polarization index.
1852 : : !!
1853 : : !! OUTPUTS
1854 : : !! rhoi_r(nfftprc,4) = Normalized orbital density in the Pauli basis.
1855 : : !!
1856 : : !! SOURCE
1857 : 0 : subroutine compute_rhoi_noncoll(this, dtset, mpi_enreg, iband, ikpt, isppol, rhoi_r)
1858 : : !Arguments ------------------------------------
1859 : : class(precon_object), intent(inout) :: this
1860 : : !scalars
1861 : : type(dataset_type),intent(in) :: dtset
1862 : : type(MPI_type), intent(in) :: mpi_enreg
1863 : : integer, intent(in) :: isppol, ikpt, iband
1864 : : real(dp), intent(inout) :: rhoi_r(this%nfftprc, 4)
1865 : :
1866 : : !Local variables-------------------------------
1867 : : !scalars
1868 : : integer :: ndat, option, tim_fourwf
1869 : : integer :: i_cg(4), i_kg(2)
1870 : : integer :: n1, n2, n3, n4, n5, n6
1871 : : integer :: istwf_k, npw_k
1872 : : !arrays
1873 : 0 : integer :: gbound(2*dtset%mgfft+8,2)
1874 : 0 : integer, allocatable :: kg_k(:, :)
1875 : 0 : real(dp), allocatable :: psi_r_up(:, :, :, :), psi_r_down(:, :, :, :)
1876 : : !dummy arguments
1877 : : integer :: dummy_int
1878 : : real(dp) :: dummy_fofgout(2, 0)
1879 : 0 : real(dp) :: dummy_denpot(dtset%ngfft(4), dtset%ngfft(5), dtset%ngfft(6))
1880 : :
1881 : : ! *************************************************************************
1882 : :
1883 : 0 : n1 = dtset%ngfft(1)
1884 : 0 : n2 = dtset%ngfft(2)
1885 : 0 : n3 = dtset%ngfft(3)
1886 : 0 : n4 = dtset%ngfft(4)
1887 : 0 : n5 = dtset%ngfft(5)
1888 : 0 : n6 = dtset%ngfft(6)
1889 : :
1890 : : ! Non collinear spins - Wafefunctions have two spin component.
1891 [ # # ]: 0 : if (dtset%nspinor == 2) then
1892 : :
1893 : : !1) Compute psi_up and psi_down in real space :
1894 [ # # # # : 0 : ABI_MALLOC(psi_r_up, (2, n4, n5, n6))
# # # # #
# # # # #
# # # # #
# ]
1895 [ # # # # : 0 : ABI_MALLOC(psi_r_down, (2, n4, n5, n6))
# # # # #
# # # # #
# # ]
1896 : : ! Input parameters for fourwf :
1897 : 0 : option = 0 ! Only do the FFT.
1898 : 0 : ndat = 1
1899 : 0 : tim_fourwf = 0
1900 [ # # ]: 0 : i_cg = this%cg_indices(:, iband, ikpt, isppol)
1901 : 0 : istwf_k = dtset%istwfk(ikpt) ! Option parameter that describes the storage of wfs at this kpt.
1902 : 0 : npw_k = this%npwarr(ikpt) ! Number of plane-wave at this kpt.
1903 [ # # # # : 0 : ABI_MALLOC(kg_k, (3, npw_k))
# # # # #
# # # ]
1904 [ # # ]: 0 : i_kg = this%kg_indices(:, ikpt)
1905 [ # # # # : 0 : kg_k = this%kg(:, i_kg(1):i_kg(2)) ! Reduced plane-wave coordinate (k+G) of this kpt.
# # # # #
# # # ]
1906 : 0 : call sphereboundary(gbound, istwf_k, kg_k, dtset%mgfft, npw_k)
1907 : : !FFT for psi_up
1908 : : call fourwf(dummy_int, dummy_denpot, this%cg(:, i_cg(1):i_cg(2)), dummy_fofgout, psi_r_up, &
1909 : : & gbound, gbound, istwf_k, kg_k, kg_k, dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
1910 [ # # # # : 0 : & dummy_int, n4, n5, n6, option, tim_fourwf, one, one)
# # # # #
# # # #
# ]
1911 : : !FFT for psi_down
1912 : : call fourwf(dummy_int, dummy_denpot, this%cg(:, i_cg(3):i_cg(4)), dummy_fofgout, psi_r_down, &
1913 : : & gbound, gbound, istwf_k, kg_k, kg_k, dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
1914 [ # # # # : 0 : & dummy_int, n4, n5, n6, option, tim_fourwf, one, one)
# # # # #
# # # #
# ]
1915 : : ! (done separately for convenience & readability)
1916 [ # # ]: 0 : ABI_FREE(kg_k)
1917 : :
1918 : : !2) Build the 4 components of the orbital density rhoi_r:
1919 : 0 : call build_non_coll_density(this, dtset, mpi_enreg, psi_r_up, psi_r_down, rhoi_r)
1920 [ # # ]: 0 : ABI_FREE(psi_r_up)
1921 [ # # ]: 0 : ABI_FREE(psi_r_down)
1922 : :
1923 : : else
1924 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): compute_rhoi_noncoll called with collinear magnetism.")
1925 : : end if
1926 : :
1927 [ # # # # ]: 0 : end subroutine compute_rhoi_noncoll
1928 : :
1929 : : !****f* m_precon/cycle_band
1930 : : !! NAME
1931 : : !! cycle_band
1932 : : !!
1933 : : !! FUNCTION
1934 : : !! Determine whether a band should be skipped on the current MPI process
1935 : : !! according to the band-distribution scheme.
1936 : : !!
1937 : : !! INPUTS
1938 : : !! mpi_enreg = Information about MPI parallelization.
1939 : : !! nband_k = Number of bands at the current k-point.
1940 : : !! iband = Band index.
1941 : : !!
1942 : : !! OUTPUTS
1943 : : !! do_not_belong_to_proc = .true. if the band is not assigned to the
1944 : : !! current process, .false. otherwise.
1945 : : !!
1946 : : !! SOURCE
1947 : 10044 : function cycle_band(mpi_enreg, nband_k, iband) result(do_not_belong_to_proc)
1948 : : !Arguments ------------------------------------
1949 : : !type(dataset_type),intent(in) :: dtset
1950 : : type(MPI_type), intent(in) :: mpi_enreg
1951 : : integer, intent(in) :: iband, nband_k
1952 : :
1953 : : !Local variables-------------------------------
1954 : : !scalars
1955 : : integer :: rank, nbdblock, blocksize
1956 : : !arrays
1957 : :
1958 : : !Returned variable-------------------------------
1959 : : logical :: do_not_belong_to_proc
1960 : :
1961 : : ! *************************************************************************
1962 : :
1963 : 10044 : rank = xmpi_comm_rank(mpi_enreg%comm_bandfft)
1964 : 10044 : nbdblock = nband_k / (mpi_enreg%nproc_band * mpi_enreg%bandpp)
1965 : 10044 : blocksize = nband_k / nbdblock
1966 : : ! Check if this band belong to the current processor (assuming bands are distributed in order).
1967 [ + + - + ]: 10044 : do_not_belong_to_proc = .not.(1 + mpi_enreg%bandpp*rank <= mod(iband, blocksize) .and. iband <=mpi_enreg%bandpp*(rank+1))
1968 : :
1969 : 10044 : end function cycle_band
1970 : :
1971 : : !****f* m_precon/precompute_rhoi
1972 : : !! NAME
1973 : : !! precompute_rhoi
1974 : : !!
1975 : : !! FUNCTION
1976 : : !! Precompute and store the normalized orbital densities rho_i(r) = |psi_i(r)|^2
1977 : : !! for all bands with a non-negligible occupation derivative, to avoid
1978 : : !! redundant FFTs during the iterative application of chi0_diag.
1979 : : !! Results are stored in this%precomputed_rhoi and indexed by
1980 : : !! this%precomputed_rhoi_indices.
1981 : : !!
1982 : : !! INPUTS
1983 : : !! dtset = All input variables for this dataset.
1984 : : !! mpi_enreg = Information about MPI parallelization.
1985 : : !!
1986 : : !! SOURCE
1987 : 10 : subroutine precompute_rhoi(this, dtset, mpi_enreg)
1988 : :
1989 : : !Arguments ------------------------------------
1990 : : class(precon_object), intent(inout) :: this
1991 : : !scalars
1992 : : type(dataset_type),intent(in) :: dtset
1993 : : type(MPI_type), intent(in) :: mpi_enreg
1994 : :
1995 : : !Local variables-------------------------------
1996 : : !scalars
1997 : : integer :: nspin, i_rhoi, isppol, ikpt, i_kpt_sppol, nband_k, iband, iband1, iband2
1998 : : !arrays
1999 : 10 : integer, allocatable :: needed_bands_bounds(:, :)
2000 : 10 : integer, allocatable :: needed_bands_number(:)
2001 : : !for band parall
2002 : : integer :: option_fourwf, ndat, blocksize, iblock, ibandblock1, ibandblock2, nbdblock, nfft_blocks
2003 : : integer :: n1, n2, n3, n4, n5, n6
2004 : : integer :: idat, idat_down
2005 : 20 : integer :: i_cg_ibandblock1(2*dtset%nspinor), i_cg_ibandblock2(2*dtset%nspinor)
2006 : 10 : real(dp), allocatable :: dummy_occ_k(:)
2007 : 10 : real(dp), allocatable :: dummy_denpot(:, :, :)
2008 : 10 : real(dp), allocatable :: rhoi_aug(:, :, :, :)
2009 : 10 : real(dp), allocatable :: psii_aug(:, :, :, :)
2010 : :
2011 : : ! *************************************************************************
2012 : :
2013 [ - + + - : 30 : ABI_MALLOC(needed_bands_bounds, (2, dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
2014 [ - + + - : 30 : ABI_MALLOC(needed_bands_number, (dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
2015 : 10 : call get_needed_bands_chi0diag(this, dtset, mpi_enreg, needed_bands_bounds, needed_bands_number)
2016 : :
2017 : : ! Allocate the array containing the precomputed rhoi
2018 [ - + ]: 10 : if (dtset%nspinor==1) then
2019 : : nspin = 1 ! Number of spin components in the orbital densities (rhoi).
2020 [ # # ]: 0 : else if (dtset%nspinor==2) then
2021 : : nspin = 4
2022 : : else
2023 : 0 : ABI_BUG("nspinor /= 1 or 2")
2024 : : end if
2025 [ - + + - : 90 : ABI_MALLOC(this%precomputed_rhoi, (this%nfftprc, nspin, sum(needed_bands_number)))
- + + - +
+ - + + -
+ - + - -
+ - + -
+ ]
2026 [ + + + + : 710 : this%precomputed_rhoi_indices = zero
+ + ]
2027 : 10 : i_rhoi = 1
2028 : :
2029 : : !Loop over spins and kpoints
2030 [ + + ]: 30 : do isppol =1, dtset%nsppol
2031 [ + + ]: 70 : do ikpt = 1, dtset%nkpt
2032 : 40 : i_kpt_sppol = ikpt+(isppol-1)*dtset%nkpt
2033 : :
2034 : : ! MPI parallelization over kpoints : cycle if kpt does not belong to current processor.
2035 : 40 : nband_k = dtset%nband(i_kpt_sppol)
2036 [ + - ]: 40 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
2037 : : cycle
2038 : : end if
2039 : :
2040 : 40 : iband1 = needed_bands_bounds(1, i_kpt_sppol)
2041 : 40 : iband2 = needed_bands_bounds(2, i_kpt_sppol)
2042 : :
2043 [ - + - - ]: 60 : if (.not. (dtset%paral_kgb == 1 .and. dtset%npband > 1)) then
2044 : : ! No parallelization over band : We loop over needed bands to compute and save the orbital densities.
2045 : :
2046 [ + + ]: 256 : do iband = iband1, iband2
2047 : :
2048 : : ! No spin or collinear spins - Wafefunctions have one spin component.
2049 [ + - ]: 216 : if (dtset%nspinor == 1) then
2050 : 216 : call compute_rhoi_coll(this, dtset, mpi_enreg, iband, ikpt, isppol, this%precomputed_rhoi(:, :, i_rhoi))
2051 : 216 : this%precomputed_rhoi_indices(iband, ikpt, isppol) = i_rhoi
2052 : 216 : i_rhoi = i_rhoi + 1
2053 : : end if
2054 : :
2055 : : ! Non collinear spins - Wavefunctions have two spins components.
2056 [ - + ]: 256 : if (dtset%nspinor == 2) then
2057 : 0 : call compute_rhoi_noncoll(this, dtset, mpi_enreg, iband, ikpt, isppol, this%precomputed_rhoi(:, :, i_rhoi))
2058 : 0 : this%precomputed_rhoi_indices(iband, ikpt, isppol) = i_rhoi
2059 : 0 : i_rhoi = i_rhoi + 1
2060 : : end if
2061 : :
2062 : : end do !iband
2063 : :
2064 : : else
2065 : : ! Parallelization over band : We first do all the needed fft, with 'prep_fourwf' that will take care of
2066 : : ! the transpose from the linalg representation to the fft representation.
2067 : : ! Then we fill the 'precomputed_rhoi' array band per band.
2068 : :
2069 : 0 : n1 = dtset%ngfft(1)
2070 : 0 : n2 = dtset%ngfft(2)
2071 : 0 : n3 = dtset%ngfft(3)
2072 : 0 : n4 = dtset%ngfft(4)
2073 : 0 : n5 = dtset%ngfft(5)
2074 : 0 : n6 = dtset%ngfft(6)
2075 : :
2076 : 0 : nbdblock=nband_k / (mpi_enreg%nproc_band * mpi_enreg%bandpp)
2077 : 0 : blocksize=nband_k / nbdblock
2078 : :
2079 : 0 : ndat = mpi_enreg%bandpp
2080 [ # # # # : 0 : ABI_MALLOC(psii_aug, (2, n4, n5, n6*ndat*dtset%nspinor))
# # # # #
# # # # #
# # # # #
# # # ]
2081 [ # # # # : 0 : ABI_MALLOC(rhoi_aug, (n4, n5, n6, nspin))
# # # # #
# # # # #
# # # # #
# # # #
# ]
2082 : :
2083 : 0 : option_fourwf = 0
2084 : :
2085 [ # # ]: 0 : do iblock = 1, nbdblock ! Loop over (LOBPCG) blocks
2086 : :
2087 : : ! 1) FFTs
2088 [ # # ]: 0 : if (dtset%nspinor==1) then
2089 : :
2090 : 0 : ibandblock1 = blocksize*(iblock-1) + 1
2091 : 0 : ibandblock2 = blocksize*(iblock)
2092 [ # # ]: 0 : i_cg_ibandblock1 = this%cg_indices(:, ibandblock1, ikpt, isppol)
2093 [ # # ]: 0 : i_cg_ibandblock2 = this%cg_indices(:, ibandblock2, ikpt, isppol)
2094 : :
2095 [ # # # # : 0 : ABI_MALLOC(dummy_occ_k, (nband_k))
# # # # #
# # # ]
2096 [ # # # # : 0 : ABI_MALLOC(dummy_denpot, (n4, n5, n6))
# # # # #
# # # # #
# # # # #
# ]
2097 : :
2098 : 0 : call bandfft_kpt_set_ikpt(ikpt, mpi_enreg)
2099 : 0 : nfft_blocks = 1 ! TODO : what is that ??
2100 : : call prep_fourwf(dummy_denpot, blocksize, this%cg(:, i_cg_ibandblock1(1):i_cg_ibandblock2(2)), &
2101 : : & psii_aug, iblock, dtset%istwfk(ikpt), dtset%mgfft, mpi_enreg, nband_k, &
2102 : : & ndat, dtset%ngfft, this%npwarr(ikpt), &
2103 [ # # # # : 0 : & n4, n5, n6, dummy_occ_k, option_fourwf, this%ucvol, dtset%wtk(ikpt), nfft_blocks)
# # # # #
# ]
2104 : :
2105 [ # # ]: 0 : ABI_FREE(dummy_occ_k)
2106 [ # # ]: 0 : ABI_FREE(dummy_denpot)
2107 : : else
2108 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): non-collinear magnetisme with band parall - TODO")
2109 : : ! TODO : How is prep_fourwf suppsed to be called with nspinor= = 2 ????
2110 : : end if
2111 : :
2112 : : ! 2) Fill precomputed_rhoi
2113 : 0 : idat = 0
2114 : :
2115 : : ! Loop over the bands of this proc (assuming bands are distributed in order).
2116 [ # # ]: 0 : do iband = ibandblock1, ibandblock2
2117 : :
2118 [ # # ]: 0 : if (cycle_band(mpi_enreg, nband_k, iband)) then
2119 : : cycle
2120 : : end if ! Checks if the band belongs to the current processor.
2121 : :
2122 : 0 : idat = idat + 1
2123 : :
2124 : : ! Check if this band is needed
2125 [ # # # # ]: 0 : if (.not. (iband1 <= iband .and. iband <= iband2)) then
2126 : : cycle
2127 : : end if
2128 : :
2129 [ # # ]: 0 : if (dtset%nspinor==1) then
2130 : :
2131 : : !Compute rhoi_aug from psii_aug
2132 [ # # # # : 0 : rhoi_aug = zero
# # # # ]
2133 : 0 : call cg_addtorho(n1, n2, n3, n4, n5, n6, 1, one, one, psii_aug(:, :, :, (idat-1)*n6+1:idat*n6), rhoi_aug(:, :, :, 1))
2134 : :
2135 : : ! Grid transfer
2136 : 0 : call transfer_grid(this, dtset, mpi_enreg, 1, rhoi_aug(:, :, :, 1), this%precomputed_rhoi(:, :, i_rhoi))
2137 : :
2138 : : ! Normalize
2139 : : this%precomputed_rhoi(:, 1, i_rhoi) = this%precomputed_rhoi(:, 1, i_rhoi) / &
2140 [ # # # # ]: 0 : & (sum(this%precomputed_rhoi(:, 1, i_rhoi)) * this%dvol)
2141 : :
2142 : : else ! Non-collinear case.
2143 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): non-collinear magnetisme with band parall - TODO")
2144 : :
2145 : : ! This assumes that in the FFT, the two spinorial components consecutively stored.
2146 : 0 : idat_down = idat +1
2147 : : call build_non_coll_density(this, dtset, mpi_enreg, psii_aug(:, :, :, (idat-1)*n6+1:idat*n6), &
2148 : 0 : & psii_aug(:, :, :, (idat_down-1)*n6+1:idat_down*n6), this%precomputed_rhoi(:, :, i_rhoi))
2149 : 0 : idat = idat_down ! Because we used two consecutive blocks of psii_aug for the two spin components of the same band.
2150 : :
2151 : : end if
2152 : : ! Save the index
2153 : 0 : this%precomputed_rhoi_indices(iband, ikpt, isppol) = i_rhoi
2154 : 0 : i_rhoi = i_rhoi + 1
2155 : :
2156 : : end do
2157 : :
2158 : : end do
2159 : :
2160 [ # # ]: 0 : ABI_FREE(rhoi_aug)
2161 [ # # ]: 0 : ABI_FREE(psii_aug)
2162 : :
2163 : : end if
2164 : :
2165 : : end do !ikpt
2166 : : end do !isppol
2167 : :
2168 [ - + ]: 10 : ABI_FREE(needed_bands_number)
2169 [ - + ]: 10 : ABI_FREE(needed_bands_bounds)
2170 : :
2171 [ - + ]: 10 : end subroutine precompute_rhoi
2172 : :
2173 : : !****f* m_precon/get_needed_bands_chi0diag
2174 : : !! NAME
2175 : : !! get_needed_bands_chi0diag
2176 : : !!
2177 : : !! FUNCTION
2178 : : !! Determine the range of bands that have a non-negligible occupation derivative
2179 : : !! f'(e_nk - e_F) at each (ikpt, isppol), i.e. the bands that contribute to
2180 : : !! chi0_diag. Bands outside this range are skipped in the loops of
2181 : : !! compute_delta_occ.
2182 : : !!
2183 : : !! INPUTS
2184 : : !! dtset = All input variables for this dataset.
2185 : : !! mpi_enreg = Information about MPI parallelization.
2186 : : !!
2187 : : !! OUTPUTS
2188 : : !! needed_bands_bounds(2, nkpt*nsppol) = For each (ikpt, isppol), the minimum
2189 : : !! (index 1) and maximum (index 2) band
2190 : : !! indices with |f'| > deigvals_tol_fp.
2191 : : !! needed_bands_number(nkpt*nsppol) = Number of needed bands at each (ikpt, isppol).
2192 : : !!
2193 : : !! SOURCE
2194 : 120 : subroutine get_needed_bands_chi0diag(this, dtset, mpi_enreg, needed_bands_bounds, needed_bands_number)
2195 : : !Arguments ------------------------------------
2196 : : class(precon_object), intent(in) :: this
2197 : : !scalars
2198 : : type(dataset_type),intent(in) :: dtset
2199 : : type(MPI_type), intent(in) :: mpi_enreg
2200 : : !arrays
2201 : : integer :: needed_bands_number(dtset%nsppol*dtset%nkpt)
2202 : : integer :: needed_bands_bounds(2, dtset%nsppol*dtset%nkpt)
2203 : :
2204 : : !Local variables-------------------------------
2205 : : !scalars
2206 : : integer :: i_eigen, i_kpt_sppol, ikpt, isppol, iband, nband_k
2207 : : real(dp) :: fp, maxocc
2208 : :
2209 : : ! *************************************************************************
2210 : 120 : maxocc = two / (dtset%nsppol * dtset%nspinor) !Maximum number of occupations (1 or 2)
2211 [ + + ]: 600 : needed_bands_number = zero
2212 : :
2213 [ + + ]: 360 : do isppol =1, dtset%nsppol
2214 [ + + ]: 840 : do ikpt = 1, dtset%nkpt
2215 : :
2216 : 480 : i_kpt_sppol = ikpt+(isppol-1)*dtset%nkpt
2217 : 480 : nband_k = dtset%nband(i_kpt_sppol)
2218 : 480 : needed_bands_bounds(1, i_kpt_sppol) = nband_k + 1
2219 : 480 : needed_bands_bounds(2, i_kpt_sppol) = 0
2220 : :
2221 [ - + ]: 480 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
2222 : : cycle
2223 : : end if
2224 : :
2225 [ + + ]: 8160 : do iband = 1, nband_k
2226 : :
2227 [ + + ]: 7680 : if (cycle_band(mpi_enreg, nband_k, iband)) then
2228 : : cycle
2229 : : end if ! Check if the band belongs to the current processor.
2230 : :
2231 : 7200 : i_eigen = get_eigen_index(dtset, iband, ikpt, isppol) ! Index of (iband, ikpt, isppol) in eigen array.
2232 : 7200 : fp = derivative_occ(dtset%occopt, this%eigen(i_eigen), this%fermie, this%precon_tsmear) * maxocc
2233 : :
2234 [ + + ]: 7680 : if (abs(fp) > this%deigvals_tol_fp) then
2235 : 2580 : needed_bands_bounds(1, i_kpt_sppol) = min(needed_bands_bounds(1, i_kpt_sppol), iband) ! iband_min
2236 : 2580 : needed_bands_bounds(2, i_kpt_sppol) = max(needed_bands_bounds(2, i_kpt_sppol), iband) ! iband_max
2237 : : end if
2238 : :
2239 : : end do
2240 : :
2241 : 720 : needed_bands_number(i_kpt_sppol) = max(needed_bands_bounds(2, i_kpt_sppol) - needed_bands_bounds(1, i_kpt_sppol) + 1, 0)
2242 : :
2243 : : end do !ikpt
2244 : : end do !isppol
2245 : :
2246 : 120 : end subroutine get_needed_bands_chi0diag
2247 : :
2248 : : !****f* m_precon/compute_delta_occ
2249 : : !! NAME
2250 : : !! compute_delta_occ
2251 : : !!
2252 : : !! FUNCTION
2253 : : !! Compute the first-order variation of the band occupations induced by a
2254 : : !! potential perturbation delta_V, within the diagonal approximation of chi0:
2255 : : !! delta_occ(nk) = f'(e_nk - e_F) * <psi_nk| delta_V |psi_nk>
2256 : : !! A Fermi-level correction is then applied to enforce electron-number conservation:
2257 : : !! delta_occ(nk) -= f'(e_nk - e_F) * delta_e_F
2258 : : !! where delta_e_F = sum_nk delta_occ(nk) / DOS(e_F).
2259 : : !!
2260 : : !! INPUTS
2261 : : !! dtset = All input variables for this dataset.
2262 : : !! mpi_enreg = Information about MPI parallelization.
2263 : : !! delta_V(nfftprc, nspden) = Potential perturbation in the Pauli basis.
2264 : : !!
2265 : : !! OUTPUTS
2266 : : !! delta_occ(mband*nkpt*nsppol) = First-order variation of the occupations.
2267 : : !!
2268 : : !! SOURCE
2269 [ - + ]: 55 : subroutine compute_delta_occ(this, dtset, mpi_enreg, delta_V, delta_occ)
2270 : : !Arguments ------------------------------------
2271 : : class(precon_object), intent(inout) :: this
2272 : : !scalars
2273 : : type(dataset_type),intent(in) :: dtset
2274 : : type(MPI_type), intent(in) :: mpi_enreg
2275 : : !arrays
2276 : : real(dp), intent(in) :: delta_V(this%nfftprc, dtset%nspden) ! In Pauli basis
2277 : : real(dp), intent(inout) :: delta_occ(:)
2278 : :
2279 : : !Local variables-------------------------------
2280 : : !scalars
2281 : : integer :: nband_k, nspin
2282 : : integer :: i_eigen, ikpt, iband, isppol, ier, ispden
2283 : : integer :: iband1, iband2, i_kpt_sppol
2284 : : real(dp) :: fp, eigenval, maxocc
2285 : : real(dp) :: dos_fermie, delta_occ_tot, delta_fermie
2286 : : !arrays
2287 : 55 : integer, allocatable :: needed_bands_bounds(:, :)
2288 : 55 : integer, allocatable :: needed_bands_number(:)
2289 : 55 : real(dp), allocatable :: rhoi_r(:, :)
2290 : : !real(dp), allocatable :: doccde(:), occ(:)
2291 : :
2292 : : ! *************************************************************************
2293 : :
2294 [ - + + - : 165 : ABI_MALLOC(needed_bands_bounds, (2, dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
2295 [ - + + - : 165 : ABI_MALLOC(needed_bands_number, (dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
2296 : 55 : call get_needed_bands_chi0diag(this, dtset, mpi_enreg, needed_bands_bounds, needed_bands_number)
2297 : :
2298 : : ! Compute the delta_occ = fi' * <rhoii, vec>
2299 [ + + ]: 3575 : delta_occ = zero
2300 : 55 : maxocc = two / (dtset%nsppol * dtset%nspinor) !Maximum number of occupations (1 or 2)
2301 : :
2302 : : ! Allocate the arrays that will contain rhoi
2303 [ - + ]: 55 : if (dtset%nspinor==1) then
2304 : : nspin = 1 ! Number of spin components in the orbital densities (rhoi).
2305 [ # # ]: 0 : else if (dtset%nspinor==2) then
2306 : : nspin = 4
2307 : : else
2308 : 0 : ABI_BUG("nspinor /= 1 or 2")
2309 : : end if
2310 [ - + + - : 220 : ABI_MALLOC(rhoi_r, (this%nfftprc, nspin))
- + + - +
- + - - +
- + ]
2311 : 55 : dos_fermie = zero
2312 : 55 : delta_occ_tot = zero
2313 : :
2314 : : ! Occupation derivatives could also be computetd with 'getnel' ... What is best ?
2315 : : !ABI_MALLOC(doccde, (size(this%occ)))
2316 : : !ABI_MALLOC(occ, (size(this%occ)))
2317 : : !option=1
2318 : : !call getnel(doccde, dummy_real, this%eigen, entropy, this%fermie, this%fermie, maxocc, &
2319 : : !& dtset%mband, dtset%nband, nelect, dtset%nkpt, dtset%nsppol, occ, dtset%occopt, &
2320 : : !& option, dtset%tphysel, dtset%tsmear, dummy_int, dtset%wtk)
2321 : : !ABI_FREE(occ)
2322 : :
2323 : : ! 1) Eigenvalue variations
2324 : : !Loop over spins and kpoints
2325 [ + + ]: 165 : do isppol =1, dtset%nsppol
2326 : :
2327 [ + + ]: 385 : do ikpt = 1, dtset%nkpt
2328 : :
2329 : 220 : i_kpt_sppol = ikpt+(isppol-1)*dtset%nkpt
2330 : 220 : nband_k = dtset%nband(i_kpt_sppol)
2331 : :
2332 : : ! MPI parallelization over kpoints : cycle if kpt does not belong to current processor.
2333 [ + - ]: 220 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
2334 : : cycle
2335 : : end if
2336 : :
2337 : 220 : iband1 = needed_bands_bounds(1, i_kpt_sppol)
2338 : 220 : iband2 = needed_bands_bounds(2, i_kpt_sppol)
2339 : :
2340 [ + + ]: 1512 : do iband = iband1, iband2 ! Loop over needed bands
2341 : :
2342 [ - + ]: 1182 : if (cycle_band(mpi_enreg, nband_k, iband)) then
2343 : : cycle
2344 : : end if ! Check if this band belong to current processor.
2345 : :
2346 : : !Indices
2347 : 1182 : i_eigen = get_eigen_index(dtset, iband, ikpt, isppol) ! Index of (iband, ikpt, isppol) in eigen array.
2348 : :
2349 : : !2.1) Computing f'(eig_i - fermie).
2350 : 1182 : eigenval = this%eigen(i_eigen)
2351 : 1182 : fp = derivative_occ(dtset%occopt, eigenval, this%fermie, this%precon_tsmear) * maxocc
2352 : : !fp = doccde(i_eigen) ! Same as derivative_occ (probably more robust)
2353 : 1182 : dos_fermie = dos_fermie + fp * dtset%wtk(ikpt)
2354 : :
2355 : : ! No spin or collinear spins - Wafefunctions have one spin component.
2356 [ + - ]: 1182 : if (dtset%nspinor == 1) then
2357 : :
2358 : : !2.2) Computing rho_i = |psi_i|^2 using fourwf (if fp is not 0).
2359 [ + - ]: 1182 : if (this%use_precomputed_rhoi) then
2360 [ + - + - : 3992796 : rhoi_r = this%precomputed_rhoi(:, :, this%precomputed_rhoi_indices(iband, ikpt, isppol)) ! TODO : useless copy here, use a pointer ?
- + - - +
+ + + ]
2361 : : else
2362 : 0 : call compute_rhoi_coll(this, dtset, mpi_enreg, iband, ikpt, isppol, rhoi_r)
2363 : : end if
2364 : :
2365 : : !2.3) delta_occ(i) = fp_i * dot(rho_i, delta_V)
2366 : : ! dot-product in the up/down basis (equal to the dot product in the Pauli basis) :
2367 : : ! rhoi_r has only one spin-component corresponding to isppol (up=down if nsppol=1, up or down if nsppol=2).
2368 [ - + ]: 1182 : if (dtset%nspden == 1) then
2369 [ # # ]: 0 : delta_occ(i_eigen) = fp * dot_product(rhoi_r(:, 1), delta_V(:, isppol)) * this%dvol
2370 [ - + ]: 1182 : elseif (dtset%nspden == 2) then
2371 [ + + ]: 3990432 : delta_occ(i_eigen) = fp * dot_product(rhoi_r(:, 1), delta_V(:, 1) + (1-2*(isppol-1)) * delta_V(:, 2)) * this%dvol
2372 : : ! delta_V(:, 1) + (1-2*(isppol-1)) * delta_V(:, 2) is delta_V in the (up/down) coordinate 'isppol'.
2373 : : end if
2374 : :
2375 : : ! Non collinear spins - Wavefunctions have two spins components.
2376 [ # # ]: 0 : elseif (dtset%nspinor == 2 .and. dtset%nspden==4) then
2377 : :
2378 : : !2.2) Computing rho_i (4-dim, in pauli basis).
2379 [ # # ]: 0 : if (this%use_precomputed_rhoi) then
2380 [ # # # # : 0 : rhoi_r = this%precomputed_rhoi(:, :, this%precomputed_rhoi_indices(iband, ikpt, isppol)) ! TODO : useless copy here, use a pointer ?
# # # # #
# # # ]
2381 : : else
2382 : 0 : call compute_rhoi_noncoll(this, dtset, mpi_enreg, iband, ikpt, isppol, rhoi_r)
2383 : : end if
2384 : :
2385 : : ! dot product in Pauli basis :
2386 : 0 : delta_occ(i_eigen) = zero
2387 [ # # ]: 0 : do ispden = 1, 4
2388 : : ! rhoi_r has 4 spin-components in the pauli basis that all needs to be multiplied to the corresponding component in delta_V
2389 [ # # ]: 0 : delta_occ(i_eigen) = delta_occ(i_eigen) + fp * dot_product(rhoi_r(:, ispden), delta_V(:, ispden)) * this%dvol
2390 : : end do
2391 : :
2392 : : else
2393 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): TODO non-collinear magnetism with nspden=/4.")
2394 : : ! The calculation above is probably true even when nspden=1, TODO: check
2395 : : end if
2396 : :
2397 : 1402 : delta_occ_tot = delta_occ_tot + delta_occ(i_eigen) * dtset%wtk(ikpt)
2398 : :
2399 : : end do
2400 : :
2401 : : end do !ikpt
2402 : : end do !isppol
2403 : :
2404 [ - + ]: 55 : ABI_FREE(rhoi_r)
2405 : :
2406 : : !MPI parallelization over kpoints : sum delta_occ on all processors.
2407 : : ier = 0
2408 : 55 : call xmpi_sum(delta_occ, mpi_enreg%comm_kptband, ier)
2409 : 55 : call xmpi_sum(delta_occ_tot, mpi_enreg%comm_kptband, ier)
2410 : 55 : call xmpi_sum(dos_fermie, mpi_enreg%comm_kptband, ier)
2411 : :
2412 : : ! 2) Fermi-level variation
2413 : :
2414 : 55 : delta_fermie = delta_occ_tot / dos_fermie
2415 : :
2416 : : !Loop over spins and kpoints to do delta_occ(eigenvalue) -= f'(eigenvalue) * delta_fermie
2417 [ + + ]: 165 : do isppol =1, dtset%nsppol
2418 [ + + ]: 385 : do ikpt = 1, dtset%nkpt
2419 : 220 : i_kpt_sppol = ikpt+(isppol-1)*dtset%nkpt
2420 : 220 : nband_k = dtset%nband(i_kpt_sppol)
2421 : :
2422 : 220 : iband1 = needed_bands_bounds(1, i_kpt_sppol)
2423 : 220 : iband2 = needed_bands_bounds(2, i_kpt_sppol)
2424 [ + + ]: 1512 : do iband = iband1, iband2 ! Loop over needed bands
2425 : :
2426 : 1182 : i_eigen = get_eigen_index(dtset, iband, ikpt, isppol)
2427 : 1182 : eigenval = this%eigen(i_eigen)
2428 : 1182 : fp = derivative_occ(dtset%occopt, eigenval, this%fermie, this%precon_tsmear) * maxocc
2429 : : !fp = doccde(i_eigen)
2430 : 1402 : delta_occ(i_eigen) = delta_occ(i_eigen) - fp * delta_fermie
2431 : :
2432 : : end do
2433 : : end do !ikpt
2434 : : end do !isppol
2435 : : !ABI_FREE(doccde)
2436 : :
2437 [ - + ]: 55 : ABI_FREE(needed_bands_bounds)
2438 [ - + ]: 55 : ABI_FREE(needed_bands_number)
2439 : :
2440 : 55 : end subroutine compute_delta_occ
2441 : :
2442 : : !****f* m_precon/compute_delta_rho_from_delta_occ_only
2443 : : !! NAME
2444 : : !! compute_delta_rho_from_delta_occ_only
2445 : : !!
2446 : : !! FUNCTION
2447 : : !! Compute the first-order density variation induced by a set of occupation
2448 : : !! variations delta_occ, neglecting wavefunction variations:
2449 : : !! delta_rho(r) = sum_nk wtk(k) * delta_occ(nk) * |psi_nk(r)|^2
2450 : : !! The result is symmetrized with symrhg and returned in the Pauli basis.
2451 : : !!
2452 : : !! INPUTS
2453 : : !! dtset = All input variables for this dataset.
2454 : : !! mpi_enreg = Information about MPI parallelization.
2455 : : !! delta_occ(mband*nkpt*nsppol) = First-order variation of the occupations.
2456 : : !!
2457 : : !! OUTPUTS
2458 : : !! delta_rho(nfftprc, nspden) = First-order density variation in the Pauli basis.
2459 : : !!
2460 : : !! SOURCE
2461 : 55 : subroutine compute_delta_rho_from_delta_occ_only(this, dtset, mpi_enreg, delta_occ, delta_rho)
2462 : : !Arguments ------------------------------------
2463 : : class(precon_object) :: this
2464 : : !scalars
2465 : : type(dataset_type),intent(in) :: dtset
2466 : : type(MPI_type), intent(in) :: mpi_enreg
2467 : : !arrays
2468 : : real(dp), intent(in) :: delta_occ(size(this%eigen))
2469 : : real(dp), intent(inout) :: delta_rho(this%nfftprc, dtset%nspden)
2470 : :
2471 : : !Local variables-------------------------------
2472 : : integer :: iband, isppol, ispden, ikpt, i_eigen, nband_k
2473 : : integer :: ier
2474 : : integer :: maxocc
2475 : : integer :: iband1, iband2, i_kpt_sppol
2476 : : real(dp) :: fp
2477 : : !arrays
2478 : 55 : integer, allocatable :: needed_bands_bounds(:, :)
2479 : 55 : integer, allocatable :: needed_bands_number(:)
2480 : 55 : real(dp), allocatable :: rhoi_r(:, :), delta_rho_g(:, :)
2481 : :
2482 : : ! *************************************************************************
2483 : :
2484 [ - + + - : 165 : ABI_MALLOC(needed_bands_bounds, (2, dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
2485 [ - + + - : 165 : ABI_MALLOC(needed_bands_number, (dtset%nkpt*dtset%nsppol))
+ - + - -
+ - + ]
2486 : 55 : call get_needed_bands_chi0diag(this, dtset, mpi_enreg, needed_bands_bounds, needed_bands_number)
2487 : :
2488 : 55 : maxocc = two / (dtset%nsppol * dtset%nspinor) !Maximum number of occupations (1 or 2)
2489 [ + + + + ]: 371415 : delta_rho = zero
2490 : :
2491 : : !Loop over spins and kpoints
2492 [ + + ]: 165 : do isppol =1, dtset%nsppol
2493 [ + + ]: 385 : do ikpt = 1, dtset%nkpt
2494 : :
2495 : 220 : i_kpt_sppol = ikpt+(isppol-1)*dtset%nkpt
2496 : 220 : nband_k = dtset%nband(i_kpt_sppol)
2497 : :
2498 : : ! MPI parallelization over kpoints : cycle if kpt does not belong to current processor.
2499 [ + - ]: 220 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
2500 : : cycle
2501 : : end if
2502 : :
2503 : 220 : iband1 = needed_bands_bounds(1, i_kpt_sppol)
2504 : 220 : iband2 = needed_bands_bounds(2, i_kpt_sppol)
2505 : :
2506 [ + + ]: 1512 : do iband = iband1, iband2 ! Loop over needed bands
2507 : :
2508 [ + - ]: 1182 : if (cycle_band(mpi_enreg, nband_k, iband)) then
2509 : : cycle
2510 : : end if ! Check if the band belongs to the current processor.
2511 : :
2512 : :
2513 : 1182 : i_eigen = get_eigen_index(dtset, iband, ikpt, isppol) ! Index of (iband, ikpt, isppol) in eigen array.
2514 : 1182 : fp = derivative_occ(dtset%occopt, this%eigen(i_eigen), this%fermie, this%precon_tsmear) * maxocc
2515 : :
2516 : : ! Compute and add the contribution to delta_rhol.
2517 [ + - ]: 1402 : if (dtset%nspinor == 1) then
2518 : : ! Collinear magnetism or no magnetism
2519 : :
2520 : 1182 : ispden = isppol
2521 [ + - ]: 1182 : if (this%use_precomputed_rhoi) then
2522 : : ! We use the precomputed orbital density.
2523 : : delta_rho(:, ispden) = delta_rho(:, ispden) + &
2524 : : & dtset%wtk(ikpt) * delta_occ(i_eigen) * &
2525 [ + + ]: 3990432 : & this%precomputed_rhoi(:, 1, this%precomputed_rhoi_indices(iband, ikpt, isppol))
2526 : : else
2527 : : ! We need to recompute the orbital density.
2528 [ # # # # : 0 : ABI_MALLOC(rhoi_r, (this%nfftprc, 1))
# # # # #
# # # ]
2529 : 0 : call compute_rhoi_coll(this, dtset, mpi_enreg, iband, ikpt, isppol, rhoi_r)
2530 : : delta_rho(:, ispden) = delta_rho(:, ispden) + &
2531 [ # # ]: 0 : & dtset%wtk(ikpt) * delta_occ(i_eigen) * rhoi_r(:, 1)
2532 [ # # ]: 0 : ABI_FREE(rhoi_r)
2533 : : end if
2534 : : ! delta_rho in up/down representation = expected representation by symrhg
2535 : :
2536 : : ! TODO : here it is assumed that nsppol=2 => nspden=2 ...
2537 : :
2538 [ # # ]: 0 : elseif (dtset%nspden == 4) then
2539 : : ! Non collinear magnetism
2540 : :
2541 [ # # ]: 0 : if (this%use_precomputed_rhoi) then
2542 : : ! We use the precomputed orbital density.
2543 [ # # ]: 0 : do ispden = 1, 4
2544 : : delta_rho(:, ispden) = delta_rho(:, ispden) + &
2545 : : & dtset%wtk(ikpt) * delta_occ(i_eigen) * &
2546 [ # # ]: 0 : & this%precomputed_rhoi(:, ispden, this%precomputed_rhoi_indices(iband, ikpt, isppol))
2547 : : end do
2548 : : else
2549 : : ! We need to recompute the orbital density.
2550 [ # # # # : 0 : ABI_MALLOC(rhoi_r, (this%nfftprc, 4))
# # # # #
# # # ]
2551 : 0 : call compute_rhoi_noncoll(this, dtset, mpi_enreg, iband, ikpt, isppol, rhoi_r)
2552 [ # # ]: 0 : do ispden = 1, 4
2553 : : delta_rho(:, ispden) = delta_rho(:, ispden) + &
2554 [ # # ]: 0 : & dtset%wtk(ikpt) * delta_occ(i_eigen) * rhoi_r(:, ispden)
2555 : : end do
2556 [ # # ]: 0 : ABI_FREE(rhoi_r)
2557 : : end if
2558 : : ! delta_rho in Pauli representation = NOT the expected representation by symrhg
2559 : :
2560 : : else
2561 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): TODO non-collinear magnetism with nspden=/4.")
2562 : : end if
2563 : :
2564 : : end do ! iband
2565 : :
2566 : : end do ! ikpt
2567 : : end do ! isppol
2568 : :
2569 [ - + ]: 55 : ABI_FREE(needed_bands_bounds)
2570 [ - + ]: 55 : ABI_FREE(needed_bands_number)
2571 : :
2572 : : ! MPI parallelization over kpoints and bands : sum delta_rho on all processors.
2573 : : ier = 0
2574 : 55 : call xmpi_sum(delta_rho, mpi_enreg%comm_kptband, ier)
2575 : :
2576 : : ! Symmetrization
2577 [ - + + - : 165 : ABI_MALLOC(delta_rho_g, (2, this%nfftprc))
+ - + - -
+ - + ]
2578 [ + - ]: 55 : if (dtset%nspinor == 1) then
2579 : : ! In collinear magnetism, we can readily apply symrhg to delta_rho (correct spin representation).
2580 : : call symrhg(1, this%gprimd, this%irrzon, mpi_enreg, dtset%nfft, dtset%nfft, dtset%ngfft, dtset%nspden, dtset%nsppol, &
2581 [ + - - - : 55 : & dtset%nsym, this%phnons, delta_rho_g, delta_rho, this%rprimd, dtset%symafm, dtset%symrel, dtset%tnons)
- - - - -
- + - - -
- - - - -
- - + -
+ ]
2582 : : else
2583 : : ! In non-collinear magnetism, we apply symrhg independantly to each spin component,
2584 : : ! to avoid having to change the spin representation of delta_rho.
2585 [ # # ]: 0 : do ispden = 1, dtset%nspden
2586 : : call symrhg(1, this%gprimd, this%irrzon, mpi_enreg, dtset%nfft, dtset%nfft, dtset%ngfft, 1, 1, &
2587 [ # # # # : 0 : & dtset%nsym, this%phnons, delta_rho_g, delta_rho(:, ispden:ispden), this%rprimd, dtset%symafm, dtset%symrel, dtset%tnons)
# # # # #
# # # # #
# # # # #
# # # #
# ]
2588 : : end do
2589 : : end if
2590 [ - + ]: 55 : ABI_FREE(delta_rho_g)
2591 : :
2592 : 55 : call to_pauli(1, delta_rho)
2593 : :
2594 : 55 : end subroutine compute_delta_rho_from_delta_occ_only
2595 : :
2596 : : !****f* m_precon/precompute_psii
2597 : : !! NAME
2598 : : !! precompute_psii
2599 : : !!
2600 : : !! FUNCTION
2601 : : !! NOT WORKING - WIP
2602 : : !! Precompute and store the real-space wavefunctions psi_i(r) as well as the
2603 : : !! corresponding orbital densities rho_i(r) = |psi_i(r)|^2 for all bands with
2604 : : !! a non-negligible occupation derivative, to avoid redundant FFTs during the
2605 : : !! iterative application of chi0_quasidiag.
2606 : : !! Results are stored in this%precomputed_psii / this%precomputed_rhoi and
2607 : : !! indexed by this%precomputed_psii_indices / this%precomputed_rhoi_indices.
2608 : : !!
2609 : : !! INPUTS
2610 : : !! dtset = All input variables for this dataset.
2611 : : !! mpi_enreg = Information about MPI parallelization.
2612 : : !!
2613 : : !! SOURCE
2614 : 0 : subroutine precompute_psii(this, dtset, mpi_enreg)
2615 : :
2616 : : !Arguments ------------------------------------
2617 : : class(precon_object), intent(inout) :: this
2618 : : !scalars
2619 : : type(dataset_type),intent(in) :: dtset
2620 : : type(MPI_type), intent(in) :: mpi_enreg
2621 : :
2622 : : !Local variables-------------------------------
2623 : : !scalars
2624 : : integer :: n1, n2, n3, n4, n5, n6
2625 : : integer :: isppol, ikpt, i_kpt_sppol, nband_k, iband, iband1, iband2
2626 : : integer :: i_psii, option, ndat, istwf_k, npw_k, idat, ispinor, icplex, tim_fourwf
2627 : 0 : integer :: i_kg(2), i_cg_iband1(2*dtset%nspinor), i_cg_iband2(2*dtset%nspinor)
2628 : : real(dp) :: sum_rhoi_r
2629 : : integer :: ifft
2630 : : logical :: band_paral
2631 : : !arrays
2632 : 0 : integer, allocatable :: needed_bands_bounds(:, :)
2633 : 0 : integer, allocatable :: needed_bands_number(:)
2634 : 0 : integer, allocatable :: kg_k(:, :)
2635 : 0 : integer :: gbound_k(2*dtset%mgfft+8,2)
2636 : 0 : real(dp), allocatable :: psii_aug(:, :, :, :)
2637 : 0 : real(dp), allocatable :: rhoi_aug(:, :, :)
2638 : : !for band parall
2639 : : integer :: option_fourwf, blocksize, iblock, ibandblock1, ibandblock2, nbdblock, nfft_blocks
2640 : 0 : integer :: i_cg_ibandblock1(2*dtset%nspinor), i_cg_ibandblock2(2*dtset%nspinor)
2641 : 0 : real(dp), allocatable :: dummy_occ_k(:)
2642 : : !dummy arguments
2643 : 0 : real(dp) :: dummy_denpot(0, dtset%ngfft(5), dtset%ngfft(6)), dummy_fofgout(2, 0)
2644 : :
2645 : : ! *************************************************************************
2646 : 0 : ABI_BUG("WIP - precompute_psii")
2647 : :
2648 [ # # # # ]: 0 : band_paral = (dtset%paral_kgb == 1 .and. dtset%npband > 1)
2649 : :
2650 : 0 : n1 = dtset%ngfft(1)
2651 : 0 : n2 = dtset%ngfft(2)
2652 : 0 : n3 = dtset%ngfft(3)
2653 : 0 : n4 = dtset%ngfft(4)
2654 : 0 : n5 = dtset%ngfft(5)
2655 : 0 : n6 = dtset%ngfft(6)
2656 : :
2657 [ # # # # : 0 : ABI_MALLOC(needed_bands_bounds, (2, dtset%nkpt*dtset%nsppol))
# # # # #
# # # ]
2658 [ # # # # : 0 : ABI_MALLOC(needed_bands_number, (dtset%nkpt*dtset%nsppol))
# # # # #
# # # ]
2659 : 0 : call get_needed_bands_chi0diag(this, dtset, mpi_enreg, needed_bands_bounds, needed_bands_number)
2660 : :
2661 : : ! Allocate the array containing the precomputed psii
2662 [ # # # # : 0 : ABI_MALLOC(this%precomputed_psii, (2, this%nfftprc, dtset%nspinor, sum(needed_bands_number)))
# # # # #
# # # # #
# # # # #
# # # #
# ]
2663 [ # # # # : 0 : this%precomputed_psii_indices = zero
# # ]
2664 [ # # # # : 0 : ABI_MALLOC(this%precomputed_rhoi, (this%nfftprc, dtset%nspinor, sum(needed_bands_number)))
# # # # #
# # # # #
# # # # #
# # # #
# ]
2665 [ # # # # : 0 : this%precomputed_rhoi_indices = zero
# # ]
2666 : 0 : i_psii = 1
2667 : :
2668 [ # # # # : 0 : ABI_MALLOC(psii_aug, (2, n4, n5, n6*dtset%mband))
# # # # #
# # # # #
# # # # #
# ]
2669 [ # # # # : 0 : ABI_MALLOC(rhoi_aug, (n4, n5, n6))
# # # # #
# # # # #
# # # # #
# ]
2670 : :
2671 : : !Loop over spins and kpoints
2672 [ # # ]: 0 : do isppol = 1, dtset%nsppol
2673 [ # # ]: 0 : do ikpt = 1, dtset%nkpt
2674 : 0 : i_kpt_sppol = ikpt+(isppol-1)*dtset%nkpt
2675 : :
2676 : : ! MPI parallelization over kpoints : cycle if kpt does not belong to current processor.
2677 : 0 : nband_k = dtset%nband(i_kpt_sppol)
2678 [ # # ]: 0 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
2679 : : cycle
2680 : : end if
2681 : :
2682 : 0 : iband1 = needed_bands_bounds(1, i_kpt_sppol)
2683 : 0 : iband2 = needed_bands_bounds(2, i_kpt_sppol)
2684 : :
2685 [ # # ]: 0 : if (band_paral) then
2686 : :
2687 [ # # ]: 0 : if (dtset%nspinor==1) then
2688 : 0 : option_fourwf = 0
2689 : :
2690 : 0 : nbdblock = nband_k / (mpi_enreg%nproc_band * mpi_enreg%bandpp)
2691 : 0 : blocksize = nband_k / nbdblock
2692 : 0 : ndat = mpi_enreg%bandpp
2693 : :
2694 [ # # ]: 0 : do iblock = 1, nbdblock ! Loop over (LOBPCG) blocks
2695 : :
2696 : 0 : ibandblock1 = blocksize*(iblock-1) + 1
2697 : 0 : ibandblock2 = blocksize*(iblock)
2698 [ # # ]: 0 : i_cg_ibandblock1 = this%cg_indices(:, ibandblock1, ikpt, isppol)
2699 [ # # ]: 0 : i_cg_ibandblock2 = this%cg_indices(:, ibandblock2, ikpt, isppol) ! Changer
2700 : :
2701 [ # # # # : 0 : ABI_MALLOC(psii_aug, (2, n4, n5, n6*ndat))
# # # # #
# # # # #
# # # # #
# # # ]
2702 [ # # # # : 0 : ABI_MALLOC(dummy_occ_k, (nband_k))
# # # # #
# # # ]
2703 : : !ABI_MALLOC(dummy_denpot, (n4, n5, n6))
2704 : :
2705 : 0 : call bandfft_kpt_set_ikpt(ikpt, mpi_enreg)
2706 : 0 : nfft_blocks = 1 ! TODO : what is that ??
2707 : : call prep_fourwf(dummy_denpot, blocksize, this%cg(:, i_cg_ibandblock1(1):i_cg_ibandblock2(2)), &
2708 : : & psii_aug(:, :, :, 1:n6*ndat), iblock, dtset%istwfk(ikpt), dtset%mgfft, mpi_enreg, nband_k, &
2709 : : & ndat, dtset%ngfft, this%npwarr(ikpt), &
2710 [ # # # # : 0 : & n4, n5, n6, dummy_occ_k, option_fourwf, this%ucvol, dtset%wtk(ikpt), nfft_blocks)
# # # # #
# ]
2711 : :
2712 [ # # ]: 0 : ABI_FREE(dummy_occ_k)
2713 : : !ABI_FREE(dummy_denpot)
2714 : :
2715 : : end do
2716 : : else
2717 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): TODO non-collinear magnetisme in precon with band paral")
2718 : : end if
2719 : :
2720 : : else
2721 : :
2722 [ # # ]: 0 : if (dtset%nspinor==1) then
2723 : :
2724 : 0 : option = 0
2725 : 0 : ndat = needed_bands_number(i_kpt_sppol)
2726 : 0 : istwf_k = dtset%istwfk(ikpt) ! Option parameter that describes the storage of wfs at this kpt.
2727 : 0 : npw_k = this%npwarr(ikpt) ! Number of plane-wave at this kpt.
2728 [ # # # # : 0 : ABI_MALLOC(kg_k, (3, npw_k))
# # # # #
# # # ]
2729 [ # # ]: 0 : i_kg = this%kg_indices(:, ikpt)
2730 [ # # # # : 0 : kg_k = this%kg(:, i_kg(1):i_kg(2))
# # # # #
# # # ]
2731 : 0 : call sphereboundary(gbound_k, istwf_k, kg_k, dtset%mgfft, npw_k) ! Computes gbound.
2732 : 0 : tim_fourwf = 0
2733 [ # # ]: 0 : i_cg_iband1 = this%cg_indices(:, iband1, ikpt, isppol)
2734 [ # # ]: 0 : i_cg_iband2 = this%cg_indices(:, iband2, ikpt, isppol)
2735 : :
2736 : : call fourwf(0, dummy_denpot, this%cg(:, i_cg_iband1(1):i_cg_iband2(2)), dummy_fofgout, &
2737 : : & psii_aug(:, :, :, 1:n6*ndat), gbound_k, gbound_k, istwf_k, kg_k, kg_k, &
2738 : : & dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, npw_k, &
2739 [ # # # # : 0 : & n4, n5, n6, option, tim_fourwf, one, one)
# # # # #
# # # #
# ]
2740 : :
2741 [ # # ]: 0 : ABI_FREE(kg_k)
2742 : :
2743 : : else
2744 : 0 : ABI_BUG("chi0-based preconditioner (iprcel=2**): TODO non-collinear magnetisme in precon")
2745 : : end if
2746 : : end if
2747 : :
2748 [ # # ]: 0 : do iband = 1, nband_k
2749 : :
2750 [ # # ]: 0 : if (cycle_band(mpi_enreg, nband_k, iband)) then
2751 : : cycle
2752 : : end if ! Checks if the band belongs to the current processor.
2753 : :
2754 : 0 : idat = idat + 1
2755 : :
2756 : : ! Check if this band is needed
2757 [ # # # # ]: 0 : if (.not. (iband1 <= iband .and. iband <= iband2)) then
2758 : : cycle
2759 : : end if
2760 : :
2761 [ # # # # : 0 : rhoi_aug = zero
# # ]
2762 : 0 : call cg_addtorho(n1, n2, n3, n4, n5, n6, 1, one, one, psii_aug(:, :, :, (idat-1)*n6+1:idat*n6), rhoi_aug)
2763 : :
2764 : : ! Grid transfers:
2765 : 0 : ispinor = 1
2766 [ # # ]: 0 : do icplex = 1, 2
2767 : 0 : call transfer_grid(this, dtset, mpi_enreg, 1, psii_aug(icplex, :, :, idat:idat+n6-1), this%precomputed_psii(icplex, :, ispinor:ispinor, i_psii))
2768 : : ! TODO : this will create a copy ... Maybe change dim order ?
2769 : : end do
2770 : 0 : call transfer_grid(this, dtset, mpi_enreg, 1, rhoi_aug, this%precomputed_rhoi(:, :, i_psii))
2771 : :
2772 : : ! Normalize psii:
2773 : 0 : sum_rhoi_r = 0
2774 [ # # ]: 0 : do ispinor = 1, dtset%nspinor
2775 [ # # ]: 0 : do ifft=1, this%nfftprc
2776 : 0 : sum_rhoi_r = sum_rhoi_r + this%precomputed_rhoi(ifft, ispinor, i_psii)
2777 : : end do
2778 [ # # # # ]: 0 : this%precomputed_psii(:, :, ispinor, i_psii) = this%precomputed_psii(:, :, ispinor, i_psii) / sqrt(sum_rhoi_r * this%dvol)
2779 [ # # ]: 0 : this%precomputed_rhoi(:, ispinor, i_psii) = this%precomputed_rhoi(:, ispinor, i_psii) / (sum_rhoi_r * this%dvol)
2780 : : end do
2781 : :
2782 : : ! Save the index for iband, ikpt, isppol in precomputed_psii and precomputed_rhoi
2783 : 0 : this%precomputed_psii_indices(iband, ikpt, isppol) = i_psii
2784 : 0 : this%precomputed_rhoi_indices(iband, ikpt, isppol) = i_psii
2785 : 0 : i_psii = i_psii + 1
2786 : :
2787 : : end do !iband
2788 : :
2789 : :
2790 : : end do !ikpt
2791 : : end do !isppol
2792 : :
2793 [ # # ]: 0 : ABI_FREE(rhoi_aug)
2794 [ # # ]: 0 : ABI_FREE(psii_aug)
2795 [ # # ]: 0 : ABI_FREE(needed_bands_number)
2796 [ # # ]: 0 : ABI_FREE(needed_bands_bounds)
2797 : :
2798 : 0 : end subroutine precompute_psii
2799 : :
2800 : : !****f* m_precon/compute_delta_wf
2801 : : !! NAME
2802 : : !! compute_delta_wf
2803 : : !!
2804 : : !! FUNCTION
2805 : : !! NOT WORKING - WIP
2806 : : !!
2807 : : !! INPUTS
2808 : : !! dtset = All input variables for this dataset.
2809 : : !! mpi_enreg = Information about MPI parallelization.
2810 : : !! delta_V =
2811 : : !!
2812 : : !! OUTPUTS
2813 : : !! delta_wf =
2814 : : !!
2815 : : !! SOURCE
2816 : : subroutine compute_delta_wf(this, dtset, mpi_enreg, delta_V, delta_wf)
2817 : : !Arguments ------------------------------------
2818 : : class(precon_object), intent(inout) :: this
2819 : : type(dataset_type), intent(in) :: dtset
2820 : : type(MPI_type), intent(in) :: mpi_enreg
2821 : : real(dp), intent(inout) :: delta_V(this%nfftprc, dtset%nspden)
2822 : : real(dp), intent(inout) :: delta_wf(:, :)
2823 : :
2824 : : !Local variables-------------------------------
2825 : : !scalars
2826 : : integer :: n1, n2, n3, n4, n5, n6
2827 : : integer :: isppol, ispden, ikpt, nband_k, npw_k, istwf_k, iband, jband
2828 : : integer :: i_eigen, j_eigen, ier, ndat, option
2829 : : integer :: i_kg(2), j_cg(2), i_cg(2)
2830 : : real(dp) :: fi, fj, ddiff, coeff
2831 : : integer :: tim_fourwf
2832 : : integer :: gbound(2*dtset%mgfft+8,2)
2833 : : real(dp) :: dotr, doti
2834 : : !arrays
2835 : : real(dp), allocatable :: delta_V_wf_i_r(:, :,:,:)
2836 : : real(dp), allocatable :: delta_V_wf_i(:,:)
2837 : : real(dp), allocatable :: delta_V_aug(:,:,:)
2838 : : !dummy
2839 : : integer :: dummy_int
2840 : : real(dp) :: dummy_real
2841 : : real(dp) :: dummy_denpot(0, dtset%ngfft(5), dtset%ngfft(6)), dummy_fofg(2, 0)
2842 : :
2843 : : ! ***************************************************************************
2844 : : ABI_BUG("WIP - compute_delta_wf")
2845 : :
2846 : : n1 = dtset%ngfft(1)
2847 : : n2 = dtset%ngfft(2)
2848 : : n3 = dtset%ngfft(3)
2849 : : n4 = dtset%ngfft(4)
2850 : : n5 = dtset%ngfft(5)
2851 : : n6 = dtset%ngfft(6)
2852 : :
2853 : : delta_wf = zero
2854 : :
2855 : : ABI_MALLOC(delta_V_wf_i_r, (2, n4, n5, n6))
2856 : : ABI_MALLOC(delta_V_wf_i, (2, dtset%mpw))
2857 : : ABI_MALLOC(delta_V_aug, (n4, n5, n6))
2858 : :
2859 : : !Loop over spins and kpoints
2860 : : do isppol = 1, dtset%nsppol
2861 : :
2862 : : ispden = isppol !TODO noncoll
2863 : : ! Transfer delta_V to the augmented (wavefunction) fft-grid
2864 : : call fftpac(ispden, mpi_enreg, dtset%nspden, n1, n2, n3, n4, n5, n6, dtset%ngfft, delta_V, delta_V_aug, 2)
2865 : :
2866 : : do ikpt = 1, dtset%nkpt
2867 : : nband_k = dtset%nband(ikpt+(isppol-1)*dtset%nkpt)
2868 : : !MPI parallelization over kpoints : cycle if kpt does not belong to current processor.
2869 : : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
2870 : : cycle
2871 : : end if
2872 : : npw_k = this%npwarr(ikpt) ! Number of plane-wave at this kpt.
2873 : : istwf_k = dtset%istwfk(ikpt) ! Option parameter that describes the storage of wfs at this kpt.
2874 : : i_kg = this%kg_indices(:, ikpt)
2875 : : call sphereboundary(gbound, istwf_k, this%kg(:, i_kg(1):i_kg(2)), dtset%mgfft, npw_k) ! Computes gbound.
2876 : :
2877 : : do iband = 1, nband_k
2878 : :
2879 : : i_eigen = get_eigen_index(dtset, iband, ikpt, isppol) ! Index of (iband, ikpt, isppol) in eigen array.
2880 : : if (abs(this%eigen(i_eigen) - this%fermie) > tol1) then ! TODO : condition as input
2881 : : cycle
2882 : : end if
2883 : : fi = this%occ(i_eigen)
2884 : :
2885 : : i_cg = this%cg_indices(:, iband, ikpt, isppol)
2886 : :
2887 : : !Input parameters for fourwf :
2888 : : ndat = 1 ! Only one FFT.
2889 : : tim_fourwf = 0
2890 : : ! Multiply the wave function by the potential variation delta_V (ifft -> real space multiplication -> fft)
2891 : : option = 0 ! ifft
2892 : : call fourwf(dummy_int, dummy_denpot, this%cg(:, i_cg(1):i_cg(2)), dummy_fofg, delta_V_wf_i_r, &
2893 : : & gbound, gbound, istwf_k, this%kg(:, i_kg(1):i_kg(2)), this%kg(:, i_kg(1):i_kg(2)), &
2894 : : & dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
2895 : : & dummy_int, n4, n5, n6, option, tim_fourwf, dummy_real, dummy_real)
2896 : : call cg_vlocpsi(n4, n5, n6, n4, n5, n6, 1, 1, delta_V_aug, delta_V_wf_i_r)
2897 : : option = 3 ! fft
2898 : : call fourwf(dummy_int, dummy_denpot, dummy_fofg, delta_V_wf_i(:, 1:npw_k), delta_V_wf_i_r, &
2899 : : & gbound, gbound, istwf_k, this%kg(:, i_kg(1):i_kg(2)), this%kg(:, i_kg(1):i_kg(2)), &
2900 : : & dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
2901 : : & dummy_int, n4, n5, n6, option, tim_fourwf, dummy_real, dummy_real)
2902 : : !write(6,*)'chi0diel compute_delta_wf - ok2 '; flush(6) !DEBUG
2903 : : ! result stored in delta_V_wf_i(:, i_cg(1):i_cg(2))
2904 : :
2905 : : do jband = 1, nband_k
2906 : : !write(6,*)'chi0diel compute_delta_wf - if yes '; flush(6) !DEBUG
2907 : : j_eigen = get_eigen_index(dtset, jband, ikpt, isppol) ! Index of (jband, ikpt, isppol) in eigen array.
2908 : :
2909 : : if (abs(this%eigen(j_eigen) - this%fermie) > tol1) then ! TODO : condition as input
2910 : : cycle
2911 : : end if
2912 : :
2913 : : if (iband == jband) then
2914 : : cycle
2915 : : end if ! i=j contribution computed in compute_delta_occ
2916 : :
2917 : : j_cg = this%cg_indices(:, jband, ikpt, isppol)
2918 : : fj = this%occ(j_eigen)
2919 : :
2920 : : ! Compute an equivalent of coeff=1/(eigen_i - eigen_j) that ensure correct compensation of the terms in compute_delta_occ
2921 : : if (abs(this%eigen(i_eigen) - this%eigen(j_eigen)) < dtset%tsmear * tol10) then
2922 : : ddiff = derivative_occ(dtset%occopt, (this%eigen(i_eigen)+this%eigen(j_eigen))/2, this%fermie, dtset%tsmear)
2923 : : else
2924 : : ddiff = (fi - fj)/(this%eigen(i_eigen) - this%eigen(j_eigen))
2925 : : end if
2926 : : coeff = ddiff * fi/(fi**2+fj**2) ! From DFTK
2927 : : !write(6,*)'chi0diel compute_delta_wf - ok3 '; flush(6) !DEBUG
2928 : :
2929 : : ! Compute dot product between wavefunction (j) and delta_V
2930 : : call dotprod_g(dotr, doti, istwf_k, npw_k, 2, this%cg(:, j_cg(1):j_cg(2)), delta_V_wf_i(:, 1:npw_k), 0, mpi_enreg%comm_spinorfft) ! TODO : check dotprof(psi_i, psi_i) = 1
2931 : : !write(6,*)'chi0diel compute_delta_wf - ok4 '; flush(6) !DEBUG
2932 : :
2933 : : delta_wf(1, i_cg(1):i_cg(2)) = delta_wf(1, i_cg(1):i_cg(2)) + &
2934 : : & coeff * ( dotr * this%cg(1, j_cg(1):j_cg(2)) - doti * this%cg(2, j_cg(1):j_cg(2)) )
2935 : : delta_wf(2, i_cg(1):i_cg(2)) = delta_wf(2, i_cg(1):i_cg(2)) + &
2936 : : & coeff * ( dotr * this%cg(2, j_cg(1):j_cg(2)) + doti * this%cg(1, j_cg(1):j_cg(2)) )
2937 : : !write(6,*)'chi0diel compute_delta_wf - ok5 '; flush(6) !DEBUG
2938 : :
2939 : : end do
2940 : : end do
2941 : : end do
2942 : : end do
2943 : :
2944 : : ABI_FREE(delta_V_wf_i_r)
2945 : : ABI_FREE(delta_V_wf_i)
2946 : : ABI_FREE(delta_V_aug)
2947 : :
2948 : : !MPI parallelization over kpoints : sum delta_occ on all processors.
2949 : : ier = 0
2950 : : call xmpi_sum(delta_wf, mpi_enreg%comm_kpt, ier)
2951 : :
2952 : : end subroutine compute_delta_wf
2953 : :
2954 : : !****f* m_precon/compute_delta_rho
2955 : : !! NAME
2956 : : !! compute_delta_rho
2957 : : !!
2958 : : !! FUNCTION
2959 : : !! NOT WORKING - WIP
2960 : : !! Compute the first-order density variation induced by both occupation
2961 : : !! variations (delta_occ) and wavefunction variations (delta_wf):
2962 : : !! delta_rho(r) = sum_nk wtk(k) * [ delta_occ(nk) * |psi_nk(r)|^2
2963 : : !! + 2 * occ(nk) * Re(delta_psi_nk(r)* . psi_nk(r)) ]
2964 : : !! The result is symmetrized with symrhg and returned in the Pauli basis.
2965 : : !!
2966 : : !! INPUTS
2967 : : !! dtset = All input variables for this dataset.
2968 : : !! mpi_enreg = Information about MPI parallelization.
2969 : : !! delta_occ(mband*nkpt*nsppol) = First-order variation of the occupations.
2970 : : !! delta_wf(2, mcg) = First-order variation of the wavefunctions in G-space.
2971 : : !!
2972 : : !! OUTPUTS
2973 : : !! delta_rho(nfftprc, nspden) = First-order density variation in the Pauli basis.
2974 : : !!
2975 : : !! SOURCE
2976 : 0 : subroutine compute_delta_rho(this, dtset, mpi_enreg, delta_occ, delta_wf, delta_rho)
2977 : : !Arguments ------------------------------------
2978 : : class(precon_object) :: this
2979 : : !scalars
2980 : : type(dataset_type),intent(in) :: dtset
2981 : : type(MPI_type), intent(in) :: mpi_enreg
2982 : : !arrays
2983 : : real(dp), intent(in) :: delta_occ(size(this%eigen))
2984 : : real(dp), intent(inout) :: delta_wf(2, size(this%cg, 2))
2985 : : real(dp), intent(inout) :: delta_rho(this%nfftprc, dtset%nspden)
2986 : :
2987 : : !Local variables-------------------------------
2988 : : integer :: iband, isppol, ispden, ikpt, istwf_k, i_eigen, nband_k, npw_k
2989 : : integer :: ier
2990 : : integer :: n1, n2, n3, n4, n5, n6
2991 : : integer :: tim_fourwf, ndat, option
2992 : : integer :: maxocc
2993 : : real(dp) :: fp
2994 : : !arrays
2995 : : integer :: i_cg(2), i_kg(2)
2996 : 0 : integer :: gbound(2*dtset%mgfft+8,2)
2997 : 0 : integer, allocatable :: kg_k(:, :)
2998 : 0 : real(dp), allocatable :: rho_aug_r_i(:, :, :), wf_aug_r_i(:, :, :, :), delta_wf_aug_r_i(:, :, :, :), delta_rho_aug_r(:, :, :, :)
2999 : 0 : real(dp), allocatable :: delta_rho_g(:, :)
3000 : : !dummy arguments
3001 : : integer :: dummy_int
3002 : : real(dp) :: dummy_real
3003 : 0 : real(dp) :: dummy_denpot(0, dtset%ngfft(5), dtset%ngfft(6)), dummy_fofgout(2, 0)
3004 : :
3005 : : ! *************************************************************************
3006 : 0 : ABI_BUG("WIP - compute_delta_rho")
3007 : :
3008 : 0 : n1 = dtset%ngfft(1)
3009 : 0 : n2 = dtset%ngfft(2)
3010 : 0 : n3 = dtset%ngfft(3)
3011 : 0 : n4 = dtset%ngfft(4)
3012 : 0 : n5 = dtset%ngfft(5)
3013 : 0 : n6 = dtset%ngfft(6)
3014 : 0 : maxocc = two / (dtset%nsppol * dtset%nspinor) !Maximum number of occupations (1 or 2)
3015 : :
3016 [ # # # # : 0 : ABI_MALLOC(delta_rho_aug_r, (n4, n5, n6, dtset%nspden))
# # # # #
# # # # #
# # # # #
# # # #
# ]
3017 [ # # # # : 0 : delta_rho_aug_r = zero
# # # # ]
3018 [ # # # # : 0 : ABI_MALLOC(rho_aug_r_i, (n4, n5, n6))
# # # # #
# # # # #
# # # # #
# ]
3019 [ # # # # : 0 : ABI_MALLOC(wf_aug_r_i, (2, n4, n5, n6))
# # # # #
# # # # #
# # # # #
# ]
3020 [ # # # # : 0 : ABI_MALLOC(delta_wf_aug_r_i, (2, n4, n5, n6))
# # # # #
# # # # #
# # ]
3021 : :
3022 : : !Loop over spins and kpoints
3023 [ # # ]: 0 : do isppol =1, dtset%nsppol
3024 [ # # ]: 0 : do ikpt = 1, dtset%nkpt
3025 : :
3026 : 0 : nband_k = dtset%nband(ikpt+(isppol-1)*dtset%nkpt)
3027 : :
3028 : : !MPI parallelization over kpoints : cycle if kpt does not belong to current processor.
3029 [ # # ]: 0 : if (proc_distrb_cycle(mpi_enreg%proc_distrb, ikpt, 1, nband_k, isppol, mpi_enreg%me_kpt)) then
3030 : : cycle
3031 : : end if
3032 : :
3033 : 0 : istwf_k = dtset%istwfk(ikpt) ! Option parameter that describes the storage of wfs at this kpt.
3034 [ # # # # ]: 0 : if (.not. (dtset%paral_kgb == 1 .and. dtset%npband > 1)) then
3035 : 0 : npw_k = this%npwarr(ikpt) ! Number of plane-wave at this kpt.
3036 [ # # # # : 0 : ABI_MALLOC(kg_k, (3, npw_k))
# # # # #
# # # ]
3037 [ # # ]: 0 : i_kg = this%kg_indices(:, ikpt)
3038 [ # # # # : 0 : kg_k = this%kg(:, i_kg(1):i_kg(2))
# # # # #
# # # ]
3039 : 0 : call sphereboundary(gbound, istwf_k, kg_k, dtset%mgfft, npw_k) ! Computes gbound.
3040 : : else
3041 : 0 : npw_k = bandfft_kpt(ikpt)%npw_tot ! Number of plane-wave (after transpose) at this kpt.
3042 [ # # # # : 0 : ABI_MALLOC(kg_k, (3, npw_k))
# # # # #
# # # ]
3043 [ # # # # : 0 : kg_k = bandfft_kpt(ikpt)%kg_k_gather ! Reduced plane-wave coordinate (k+G) of this kpt (after transpose).
# # # # #
# # # # #
# # ]
3044 : 0 : call sphereboundary(gbound, istwf_k, kg_k, dtset%mgfft, npw_k)
3045 : : end if ! TODO : Not very nice to have a if here ....
3046 : :
3047 [ # # ]: 0 : do iband = 1, nband_k
3048 : :
3049 [ # # ]: 0 : if (cycle_band(mpi_enreg, nband_k, iband)) then
3050 : : cycle
3051 : : end if ! Check if the band belongs to the current processor.
3052 : :
3053 : : !Indices
3054 : 0 : i_eigen = get_eigen_index(dtset, iband, ikpt, isppol) ! Index of (iband, ikpt, isppol) in eigen array.
3055 : 0 : fp = derivative_occ(dtset%occopt, this%eigen(i_eigen), this%fermie, this%precon_tsmear) * maxocc
3056 : :
3057 [ # # ]: 0 : if (abs(fp) > this%deigvals_tol_fp) then
3058 : :
3059 : : !Input parameters for fourwf :
3060 : 0 : ndat = 1 ! Only one FFT.
3061 : 0 : tim_fourwf = 0
3062 [ # # # # : 0 : rho_aug_r_i = zero
# # ]
3063 : 0 : option = 1
3064 : :
3065 : : !1) Contribution of the occupation variation
3066 : : ! IFFT for wavefunction
3067 [ # # # # ]: 0 : if (.not. (dtset%paral_kgb == 1 .and. dtset%npband > 1)) then
3068 [ # # ]: 0 : i_cg = this%cg_indices(:, iband, ikpt, isppol) ! Indices range of (iband, ikpt, isppol) in cg array
3069 : : call fourwf(1, rho_aug_r_i, this%cg(:, i_cg(1):i_cg(2)), dummy_fofgout, wf_aug_r_i, &
3070 : : & gbound, gbound, istwf_k, kg_k, kg_k, &
3071 : : & dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
3072 [ # # # # : 0 : & dummy_int, n4, n5, n6, option, tim_fourwf, one, one)
# # # # #
# # # #
# ]
3073 : : else
3074 : : !i_cg = this%cg_fft_indices(:, iband, ikpt, isppol) ! Indices range of (iband, ikpt, isppol) in cg array
3075 : : !call fourwf(1, rho_aug_r_i, this%cg_fft(:, i_cg(1):i_cg(2)), dummy_fofgout, wf_aug_r_i, &
3076 : : !& gbound, gbound, istwf_k, kg_k, kg_k, &
3077 : : !& dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
3078 : : !& dummy_int, n4, n5, n6, option, tim_fourwf, one, one)
3079 : : end if ! TODO : change this to remove if ! (use pointers ?)
3080 : :
3081 : : ! Compute and add the contribution to delta_rho
3082 [ # # ]: 0 : if (dtset%nspinor == 1) then
3083 : 0 : ispden = isppol
3084 : : delta_rho_aug_r(:, :, :, ispden) = delta_rho_aug_r(:, :, :, ispden) + &
3085 [ # # # # : 0 : & dtset%wtk(ikpt)/this%ucvol * delta_occ(i_eigen) * rho_aug_r_i
# # ]
3086 : : else
3087 : 0 : ABI_BUG("Non collinear not implemented")
3088 : : end if
3089 : :
3090 : : !2) Contribution of wavefunction variation (if applicable)
3091 : : if (.false.) then
3092 : : !if (norm2(delta_wf(:, i_cg(1):i_cg(2))) > tol14) then ! TODO : what tol ?
3093 : : ! TODO : his part is probably incorrect !
3094 : : ! IFFT for delta_wf (wavefunction variation)
3095 : : call fourwf(1, dummy_denpot, delta_wf(:, i_cg(1):i_cg(2)), dummy_fofgout, delta_wf_aug_r_i, &
3096 : : & gbound, gbound, istwf_k, this%kg(:, i_kg(1):i_kg(2)), this%kg(:, i_kg(1):i_kg(2)), &
3097 : : & dtset%mgfft, mpi_enreg, ndat, dtset%ngfft, npw_k, &
3098 : : & dummy_int, n4, n5, n6, 0, tim_fourwf, dummy_real, dummy_real)
3099 : :
3100 : : ! Sum over MPI processes (for parallelization over bands).
3101 : : ier = 0
3102 : : call xmpi_sum(delta_wf_aug_r_i, mpi_enreg%comm_bandfft, ier)
3103 : :
3104 : : ! Compute and add the contribution to delta_rho
3105 : : if (dtset%nspinor == 1) then
3106 : : ispden = isppol
3107 : : delta_rho_aug_r(:, :, :, ispden) = delta_rho_aug_r(:, :, :, ispden) + &
3108 : : & dtset%wtk(ikpt) * this%occ(i_eigen) * &
3109 : : & ((delta_wf_aug_r_i(1, :, : , :)*wf_aug_r_i(1, :, :, :)) + &
3110 : : & (delta_wf_aug_r_i(2, :, : , :)*wf_aug_r_i(2, :, :, :))) ! TODO : false ?
3111 : : else
3112 : : ABI_BUG("Non collinear not implemented")
3113 : : end if
3114 : : end if
3115 : : end if
3116 : :
3117 : : end do ! iband
3118 : :
3119 [ # # ]: 0 : ABI_FREE(kg_k)
3120 : : end do ! ikpt
3121 : : end do ! isppol
3122 : :
3123 [ # # ]: 0 : ABI_FREE(rho_aug_r_i)
3124 [ # # ]: 0 : ABI_FREE(wf_aug_r_i)
3125 [ # # ]: 0 : ABI_FREE(delta_wf_aug_r_i)
3126 : :
3127 [ # # ]: 0 : do ispden=1, dtset%nspden
3128 : 0 : call transfer_grid(this, dtset, mpi_enreg, ispden, delta_rho_aug_r(:, :, :, ispden), delta_rho)
3129 : : end do
3130 : :
3131 [ # # ]: 0 : ABI_FREE(delta_rho_aug_r)
3132 : :
3133 : : ! MPI parallelization over kpoints and bands : sum delta_rho on all processors.
3134 : : ier = 0
3135 : 0 : call xmpi_sum(delta_rho, mpi_enreg%comm_kptband, ier)
3136 : :
3137 [ # # # # : 0 : ABI_MALLOC(delta_rho_g, (2, this%nfftprc))
# # # # #
# # # ]
3138 : : call symrhg(1, this%gprimd, this%irrzon, mpi_enreg, dtset%nfft, dtset%nfft, dtset%ngfft, dtset%nspden, dtset%nsppol, &
3139 [ # # # # : 0 : & dtset%nsym, this%phnons, delta_rho_g, delta_rho, this%rprimd, dtset%symafm, dtset%symrel, dtset%tnons) ! TODO : carefull with tnons and symrel (do they get updated during structure optimization ?)
# # # # #
# # # # #
# # # # #
# # # #
# ]
3140 [ # # ]: 0 : ABI_FREE(delta_rho_g)
3141 : : ! TODO : deal with symmetries when spin (nsppol in non coll)
3142 : :
3143 : 0 : call to_pauli(1, delta_rho)
3144 : :
3145 : 0 : end subroutine compute_delta_rho
3146 : :
3147 : : !****f* m_precon/apply_chi0_diag
3148 : : !! NAME
3149 : : !! apply_chi0_diag
3150 : : !!
3151 : : !! FUNCTION
3152 : : !! Apply the diagonal approximation of the independent-particle susceptibility
3153 : : !! chi0 to a vector vec_r (in place). The diagonal approximation retains only
3154 : : !! the intraband (n=n') terms:
3155 : : !! (chi0_diag * v)(r) = sum_nk wtk(k) * f'(e_nk - e_F) * <psi_nk|v|psi_nk> * |psi_nk(r)|^2
3156 : : !! with a Fermi-level correction to conserve the electron number.
3157 : : !!
3158 : : !! INPUTS
3159 : : !! dtset = All input variables for this dataset.
3160 : : !! mpi_enreg = Information about MPI parallelization.
3161 : : !!
3162 : : !! SIDE EFFECTS
3163 : : !! vec_r(nfftprc, nspden) = On input: potential vector in the Pauli basis.
3164 : : !! On output: chi0_diag * vec_r in the Pauli basis (density).
3165 : : !!
3166 : : !! SOURCE
3167 : 55 : subroutine apply_chi0_diag(this, dtset, mpi_enreg, vec_r)
3168 : :
3169 : : !Arguments ------------------------------------
3170 : : class(precon_object) :: this
3171 : : !scalars
3172 : : type(dataset_type),intent(in) :: dtset
3173 : : type(MPI_type), intent(in) :: mpi_enreg
3174 : : !arrays
3175 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
3176 : :
3177 : : !Local variables-------------------------------
3178 : : !arrays
3179 : 55 : real(dp), allocatable :: delta_occ(:)
3180 : :
3181 : : ! *************************************************************************
3182 : :
3183 [ - + + - : 165 : ABI_MALLOC(delta_occ, (size(this%eigen)))
+ - + - -
+ - + ]
3184 : 55 : call compute_delta_occ(this, dtset, mpi_enreg, vec_r, delta_occ)
3185 : 55 : call compute_delta_rho_from_delta_occ_only(this, dtset, mpi_enreg, delta_occ, vec_r)
3186 : :
3187 [ - + ]: 55 : ABI_FREE(delta_occ)
3188 : :
3189 : 55 : end subroutine apply_chi0_diag
3190 : :
3191 : : !****f* m_precon/apply_chi0_quasidiag
3192 : : !! NAME
3193 : : !! apply_chi0_quasidiag
3194 : : !!
3195 : : !! FUNCTION
3196 : : !! NOT WORKING - WIP
3197 : : !! Apply the quasidiagonal approximation of chi0 to a vector vec_r (in place).
3198 : : !! Like chi0_diag but also include some wavefunction variation contributions.
3199 : : !!
3200 : : !! INPUTS
3201 : : !! dtset = All input variables for this dataset.
3202 : : !! mpi_enreg = Information about MPI parallelization.
3203 : : !!
3204 : : !! SIDE EFFECTS
3205 : : !! vec_r(nfftprc, nspden) = On input: potential vector in the Pauli basis.
3206 : : !! On output: chi0_quasidiag * vec_r in the Pauli basis.
3207 : : !!
3208 : : !! SOURCE
3209 : 0 : subroutine apply_chi0_quasidiag(this, dtset, mpi_enreg, vec_r)
3210 : :
3211 : : !Arguments ------------------------------------
3212 : : class(precon_object) :: this
3213 : : !scalars
3214 : : type(dataset_type),intent(in) :: dtset
3215 : : type(MPI_type), intent(in) :: mpi_enreg
3216 : : !arrays
3217 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
3218 : :
3219 : : !Local variables-------------------------------
3220 : : !arrays
3221 : 0 : real(dp), allocatable :: delta_occ(:), delta_wf(:, :)
3222 : :
3223 : : ! *************************************************************************
3224 : :
3225 [ # # # # : 0 : ABI_MALLOC(delta_occ, (size(this%eigen)))
# # # # #
# # # ]
3226 [ # # # # : 0 : ABI_MALLOC(delta_wf, (2, size(this%cg, 2)))
# # # # #
# # # ]
3227 : 0 : call compute_delta_occ(this, dtset, mpi_enreg, vec_r, delta_occ)
3228 [ # # # # ]: 0 : delta_wf = zero
3229 : : !call compute_delta_wf(this, dtset, mpi_enreg, vec_r, delta_wf)
3230 [ # # # # ]: 0 : vec_r = zero
3231 : 0 : call compute_delta_rho(this, dtset, mpi_enreg, delta_occ, delta_wf, vec_r)
3232 : :
3233 [ # # ]: 0 : ABI_FREE(delta_occ)
3234 [ # # ]: 0 : ABI_FREE(delta_wf)
3235 : :
3236 : 0 : end subroutine apply_chi0_quasidiag
3237 : :
3238 : : !****f* m_precon/apply_chi0
3239 : : !! NAME
3240 : : !! apply_chi0
3241 : : !!
3242 : : !! FUNCTION
3243 : : !! NOT WORKING -WIP
3244 : : !! Apply the model (determined by iprcel) chi0 operator to the vector vec_r (in place).
3245 : : !!
3246 : : !! INPUTS
3247 : : !! dtset = All input variables for this dataset.
3248 : : !! mpi_enreg = Information about MPI parallelization.
3249 : : !! ispden = Index of spin-density component.
3250 : : !!
3251 : : !! SIDE EFFECTS
3252 : : !! vec_r (nfftprc, nspden) = Vector (in direct space) to which the model chi0 operator is applied (in place).
3253 : : !! When nspden > 1 vec_r is in the Pauli basis.
3254 : : !!
3255 : : !! SOURCE
3256 : 0 : subroutine apply_chi0(this, dtset, vec_r)
3257 : :
3258 : : !Arguments ------------------------------------
3259 : : class(precon_object) :: this
3260 : : !scalars
3261 : : type(dataset_type),intent(in) :: dtset
3262 : : !arrays
3263 : : real(dp), intent(inout) :: vec_r(this%nfftprc, dtset%nspden)
3264 : :
3265 : : !Local variables-------------------------------
3266 : : !scalars
3267 : : integer :: ispden
3268 : :
3269 : : ! *************************************************************************
3270 : :
3271 : : !Kerker with user_defined parameter dielng
3272 [ # # ]: 0 : if (this%iprcel == 210) then
3273 : 0 : ispden = 1
3274 [ # # ]: 0 : vec_r(:, ispden) = (-1/(4*pi*(this%dielng)**2)) * vec_r(:, ispden)
3275 [ # # ]: 0 : do ispden = 2, dtset%nspden
3276 [ # # ]: 0 : vec_r(:, ispden) = 0
3277 : : end do
3278 : : end if
3279 : :
3280 : : !Kerker based on the DOS.
3281 [ # # ]: 0 : if (this%iprcel == 211) then
3282 : 0 : ispden = 1
3283 [ # # ]: 0 : vec_r(:, ispden) = -this%dos(1) * vec_r(:, ispden)
3284 [ # # ]: 0 : do ispden = 2, dtset%nspden
3285 [ # # ]: 0 : vec_r(:, ispden) = 0
3286 : : end do
3287 : : end if
3288 : :
3289 : : !Kerker based on the DOS, that can be different between the up and down chanels in spin-polarized cases.
3290 [ # # ]: 0 : if (this%iprcel == 201) then
3291 [ # # ]: 0 : vec_r(:, 1) = 0
3292 [ # # ]: 0 : do ispden = 1, dtset%nspden
3293 [ # # ]: 0 : vec_r(:, 1) = vec_r(:, 1) - this%dos(ispden) * vec_r(:, ispden)
3294 : : end do
3295 [ # # ]: 0 : do ispden = 2, dtset%nspden
3296 [ # # ]: 0 : vec_r(:, ispden) = - this%dos(ispden) * vec_r(:, 1)
3297 : : end do
3298 : : end if
3299 : :
3300 : : !LDOS model
3301 [ # # ]: 0 : if (this%iprcel == 200 .or. this%iprcel == 212) then
3302 : 0 : call apply_chi0_ldos(this, dtset, vec_r)
3303 : : end if
3304 : :
3305 : 0 : end subroutine apply_chi0
3306 : :
3307 : : !!***
3308 : : !!****f* ABINIT/apply_adjdielmat
3309 : : !! NAME
3310 : : !! apply_adjdielmat
3311 : : !!
3312 : : !! FUNCTION
3313 : : !! Apply the adjoint dielectric matrix I-chi0*vc to the density rho_r (given in the Fourier space)
3314 : : !! with a model chi0 operator.
3315 : : !!
3316 : : !! INPUTS
3317 : : !! dtset = All input variables for this dataset.
3318 : : !! mpi_enreg = Information about MPI parallelization.
3319 : : !! rho_r = Density vector (in direct space, in Pauli basis).
3320 : : !!
3321 : : !! OUTPUT
3322 : : !! adjdielmat_rho_r = adjdielmat * rho_r
3323 : : !!
3324 : : !! NOTES
3325 : : !!
3326 : : !! SOURCE
3327 : 90 : subroutine apply_adjdielmat(this, dtset, mpi_enreg, rho_r, adjdielmat_rho_r)
3328 : :
3329 : : !Arguments ------------------------------------
3330 : : class(precon_object) :: this
3331 : : !scalars
3332 : : type(dataset_type),intent(in) :: dtset
3333 : : type(MPI_type),intent(in) :: mpi_enreg
3334 : : !arrays
3335 : : real(dp), intent(in) :: rho_r(this%nfftprc, dtset%nspden)
3336 : : real(dp), intent(inout) :: adjdielmat_rho_r(this%nfftprc, dtset%nspden)
3337 : : !Local variables-------------------------------
3338 : 90 : real(dp), allocatable :: chi0_kxc_rho_r(:, :)
3339 : :
3340 : : ! *************************************************************************
3341 [ + - ]: 90 : if (this%use_precon) then
3342 : :
3343 [ - + ]: 90 : if (this%iprcel == 299) then
3344 : : ! P=I : No preconditioning
3345 [ # # # # ]: 0 : adjdielmat_rho_r = rho_r
3346 : :
3347 [ + + ]: 90 : elseif (this%iprcel == 200) then
3348 : : ! More efficient implementation for the LDOS preconditioner.
3349 : 35 : call apply_adjdielmat_ldos(this, dtset, mpi_enreg, rho_r, adjdielmat_rho_r)
3350 : :
3351 [ + - ]: 55 : elseif (this%iprcel == 202) then
3352 : : ! When iprcel = 202, P = (I - chi0_ldos*vc - chi0_diag*Kxc)
3353 : :
3354 : : !1) Compute adjdielmat_rho_r = rho_r - chi0_ldos * vc *rho_r
3355 : 55 : call apply_adjdielmat_ldos(this, dtset, mpi_enreg, rho_r, adjdielmat_rho_r)
3356 : :
3357 : : !2) Add -(chi0_diag * Kxc * rho_r) to adjdielmat_rho_r
3358 [ - + + - : 220 : ABI_MALLOC(chi0_kxc_rho_r, (this%nfftprc, dtset%nspden))
- + + - +
- + - - +
- + ]
3359 : :
3360 : : !2.2) Apply Kxc to vec_r
3361 : 55 : call apply_kxc(this, dtset, mpi_enreg, rho_r, chi0_kxc_rho_r)
3362 : : !2.3) Apply chi0_diag to Kxc*vec_r (in place)
3363 : 55 : call apply_chi0_diag(this, dtset, mpi_enreg, chi0_kxc_rho_r)
3364 : : !2.5) Add this contribution to adjdielmat_rho_r
3365 [ + + + + ]: 371415 : adjdielmat_rho_r = adjdielmat_rho_r - chi0_kxc_rho_r
3366 : :
3367 [ - + ]: 55 : ABI_FREE(chi0_kxc_rho_r)
3368 : :
3369 [ # # ]: 0 : elseif (this%iprcel == 203) then
3370 : : ! When iprcel = 203, P = (I - chi0_ldos*vc - chi0_quasidiag*Kxc)
3371 : :
3372 : : !1) Compute adjdielmat_rho_r = rho_r - chi0_ldos * vc *rho_r
3373 : 0 : call apply_adjdielmat_ldos(this, dtset, mpi_enreg, rho_r, adjdielmat_rho_r)
3374 : :
3375 : : !2) Add -(chi0_diag * Kxc * rho_r) to adjdielmat_rho_r
3376 [ # # # # : 0 : ABI_MALLOC(chi0_kxc_rho_r, (this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
3377 : :
3378 : : !2.2) Apply Kxc to vec_r
3379 : 0 : call apply_kxc(this, dtset, mpi_enreg, rho_r, chi0_kxc_rho_r)
3380 : : !2.3) Apply chi0_quasidiag to Kxc*vec_r (in place)
3381 : 0 : call apply_chi0_quasidiag(this, dtset, mpi_enreg, chi0_kxc_rho_r)
3382 : : !2.5) Add this contribution to adjdielmat_rho_r
3383 [ # # # # ]: 0 : adjdielmat_rho_r = adjdielmat_rho_r - chi0_kxc_rho_r
3384 : :
3385 [ # # ]: 0 : ABI_FREE(chi0_kxc_rho_r)
3386 : :
3387 : : else
3388 : : ! In the general case, P = (I - K*chi0_model) where K and chi0_model are defined
3389 : : ! in the subroutine apply_kernel and apply_chi0 (depending on iprcel).
3390 : :
3391 [ # # # # ]: 0 : adjdielmat_rho_r = rho_r
3392 : : !1) Apply the Kernel (vc or vc + Kxc depending on iprcel)
3393 : 0 : call apply_kernel(this, dtset, mpi_enreg, adjdielmat_rho_r)
3394 : : !2) Applythe model chi0 operator
3395 : 0 : call apply_chi0(this, dtset, adjdielmat_rho_r)
3396 : : !3) adjdielmat_rho_r = rho_r - K * chi0 * rho_r = adjdielmat * rho_r
3397 [ # # # # ]: 0 : adjdielmat_rho_r = rho_r - adjdielmat_rho_r
3398 : :
3399 : : end if
3400 : :
3401 : : end if
3402 : 90 : end subroutine apply_adjdielmat
3403 : : !!***
3404 : :
3405 : : !!****f* ABINIT/apply_dielmat
3406 : : !! NAME
3407 : : !! apply_dielmat
3408 : : !!
3409 : : !! FUNCTION
3410 : : !! Apply the model dielectric matrix (I - K*chi0) to the potential v_r (given in the direct/real space),
3411 : : !! with a model chi0 operator (contained in precon).
3412 : : !!
3413 : : !! INPUTS
3414 : : !! dtset = All input variables for this dataset.
3415 : : !! mpi_enreg = Information about MPI parallelization.
3416 : : !! v_r = Potential vector (in real space, in Pauli basis)
3417 : : !!
3418 : : !! OUTPUT
3419 : : !! dielmat_v_r = dielmat * v_r
3420 : : !!
3421 : : !! NOTES
3422 : : !!
3423 : : !! SOURCE
3424 : 0 : subroutine apply_dielmat(this, dtset, mpi_enreg, v_r, dielmat_v_r)
3425 : :
3426 : : !Arguments ------------------------------------
3427 : : class(precon_object) :: this
3428 : : !scalars
3429 : : type(dataset_type),intent(in) :: dtset
3430 : : type(MPI_type),intent(in) :: mpi_enreg
3431 : : !arrays
3432 : : real(dp), intent(in) :: v_r(this%nfftprc, dtset%nspden)
3433 : : real(dp), intent(inout) :: dielmat_v_r(this%nfftprc, dtset%nspden)
3434 : : !Local variables-------------------------------
3435 : 0 : real(dp), allocatable :: kxc_chi0_v_r(:, :), chi0_v_r(:, :)
3436 : :
3437 : : ! *************************************************************************
3438 [ # # ]: 0 : if (this%use_precon) then
3439 : :
3440 [ # # ]: 0 : if (this%iprcel == 299) then
3441 : : ! P=I : No preconditioning
3442 [ # # # # ]: 0 : dielmat_v_r = v_r
3443 : :
3444 [ # # ]: 0 : elseif (this%iprcel == 200) then
3445 : : ! More efficient implementation for the LDOS preconditioner.
3446 : 0 : call apply_dielmat_ldos(this, dtset, mpi_enreg, v_r, dielmat_v_r)
3447 : :
3448 [ # # ]: 0 : elseif (this%iprcel == 202) then
3449 : : ! When iprcel = 202, P = (I - vc*chi0_ldos - Kxc*chi0_diag)
3450 : :
3451 : : !1) Compute dielmat_v_r = v_r - vc * chi0_ldos *v_r
3452 : 0 : call apply_dielmat_ldos(this, dtset, mpi_enreg, v_r, dielmat_v_r)
3453 : :
3454 : : !2) Add -(Kxc * chi0_quasidiag * v_r) to dielmat_v_r
3455 : :
3456 : : !2.1) Apply chi0_quasidiag to v_r
3457 [ # # # # : 0 : ABI_MALLOC(chi0_v_r, (this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
3458 [ # # # # : 0 : chi0_v_r = v_r
# # # # #
# ]
3459 : 0 : call apply_chi0_diag(this, dtset, mpi_enreg, chi0_v_r)
3460 : : !2.2) Apply Kxc to chi0*v_r
3461 [ # # # # : 0 : ABI_MALLOC(kxc_chi0_v_r, (this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
3462 : 0 : call apply_kxc(this, dtset, mpi_enreg, chi0_v_r, kxc_chi0_v_r)
3463 : : !2.3) Add this contribution to dielmat_v_r
3464 [ # # # # ]: 0 : dielmat_v_r = dielmat_v_r - kxc_chi0_v_r
3465 [ # # ]: 0 : ABI_FREE(kxc_chi0_v_r)
3466 [ # # ]: 0 : ABI_FREE(chi0_v_r)
3467 : :
3468 [ # # ]: 0 : elseif (this%iprcel == 203) then
3469 : : ! When iprcel = 203 , P = (I - vc*chi0_ldos - Kxc*chi0_quasidiag)
3470 : :
3471 : : !1) Compute dielmat_v_r = v_r - vc * chi0_ldos *v_r
3472 : 0 : call apply_dielmat_ldos(this, dtset, mpi_enreg, v_r, dielmat_v_r)
3473 : :
3474 : : !2) Add -(Kxc * chi0_quasidiag * v_r) to dielmat_v_r
3475 : :
3476 : : !2.1) Apply chi0_quasidiag to v_r
3477 [ # # # # : 0 : ABI_MALLOC(chi0_v_r, (this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
3478 [ # # # # : 0 : chi0_v_r = v_r
# # # # #
# ]
3479 : 0 : call apply_chi0_quasidiag(this, dtset, mpi_enreg, chi0_v_r)
3480 : : !2.2) Apply Kxc to chi0*v_r
3481 [ # # # # : 0 : ABI_MALLOC(kxc_chi0_v_r, (this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
3482 : 0 : call apply_kxc(this, dtset, mpi_enreg, chi0_v_r, kxc_chi0_v_r)
3483 : : !2.3) Add this contribution to dielmat_v_r
3484 [ # # # # ]: 0 : dielmat_v_r = dielmat_v_r - kxc_chi0_v_r
3485 [ # # ]: 0 : ABI_FREE(kxc_chi0_v_r)
3486 [ # # ]: 0 : ABI_FREE(chi0_v_r)
3487 : :
3488 : : else
3489 : : ! In the general case, P = (I - K*chi0_model) where K and chi0_model are defined
3490 : : ! in the subroutine apply_kernel and apply_chi0 (depending on iprcel).
3491 : :
3492 [ # # # # ]: 0 : dielmat_v_r = v_r
3493 : : !1) Apply the model chi0 operator
3494 : 0 : call apply_chi0(this, dtset, dielmat_v_r)
3495 : : !2) Apply the Kernel (vc or vc + Kxc depending on iprcel)
3496 : 0 : call apply_kernel(this, dtset, mpi_enreg, dielmat_v_r)
3497 : : !3) dielmat_v_r = v_r - K * chi0 * v_r = dielmat * v_r
3498 [ # # # # ]: 0 : dielmat_v_r = v_r - dielmat_v_r
3499 : :
3500 : : end if
3501 : :
3502 : : end if
3503 : 0 : end subroutine apply_dielmat
3504 : : !!***
3505 : :
3506 : : !****f* m_precon/apply_precon
3507 : : !! NAME
3508 : : !! apply_precon
3509 : : !!
3510 : : !! FUNCTION
3511 : : !! Apply a the preconditioner P^-1 to a given input vector 'vresid' where P is a model for the
3512 : : !! dielectric matrix or its adjoint based of a model of the non interacting susceptibility chi0.
3513 : : !! More precisely,
3514 : : !! - if we are preconditioning potentials ('optres'=0), P is a model of the dielectric matrix (I-K*chi0)
3515 : : !! - if we are preconditioning densities ('optres'=1), P is a model of the adjoint dielectric matrix (I-chi0*K).
3516 : : !! The approximation are defined in 'apply_dielmat' and 'apply_adjdielmat' by Abinit input 'iprcel'.
3517 : : !!
3518 : : !! The preconditioner is applied by solving the linear equation P * 'vrespc' = 'vresid' iteratively,
3519 : : !! either using the GMRES method if P is well conditioned (positive definite) or using Ridge/Tikhonov regularization
3520 : : !! with the conjugate gradient if P might be ill-conditioned.
3521 : : !!
3522 : : !! INPUTS
3523 : : !! dtset = All input variables for this dataset.
3524 : : !! mpi_enreg = Information about MPI parallelization.
3525 : : !! optreal = Integer flag indicating whether the input is in real space (1) or reciprocal space (2).
3526 : : !! optres = Integer flag indicating whether we are preconditioning densities (1) or potentials (0).
3527 : : !! vresid = Residual vector to which the preconditioner is applied.
3528 : : !!
3529 : : !! OUTPUTS
3530 : : !! vrespc = Preconditioned residual vector.
3531 : : !!
3532 : : !! NOTES
3533 : : !! 'vresid' and 'vrespc' have a different shape than the typical density/potential vectors
3534 : : !! in the rest of this file, to match the shape needed in 'm_prcref'.
3535 : : !!
3536 : : !! SOURCE
3537 : 18 : subroutine apply_precon(this, dtset, mpi_enreg, optreal, optres, vresid, vrespc)
3538 : : !Arguments ------------------------------------
3539 : : class(precon_object), intent(inout) :: this
3540 : : type(dataset_type),intent(in) :: dtset
3541 : : type(MPI_type),intent(in) :: mpi_enreg
3542 : : integer :: optreal, optres
3543 : : !arrays
3544 : : real(dp), intent(in) :: vresid(optreal*this%nfftprc, dtset%nspden)
3545 : : real(dp), intent(inout) :: vrespc(optreal*this%nfftprc, dtset%nspden)
3546 : : !Local variables-------------------------------
3547 : : !scalars
3548 : : integer :: ispden, start_ispden, end_ispden, n
3549 : : !arrays
3550 : 18 : real(dp), allocatable :: rhs(:), est(:), P_rhs(:)
3551 : 18 : real(dp), allocatable :: work_g(:, :, :)
3552 : :
3553 : : ! *************************************************************************
3554 [ + - - + : 36 : if (this%use_precon) then
- + - + ]
3555 : :
3556 : : !0.0) Update precon object
3557 : 18 : call precon_update(this, dtset, mpi_enreg)
3558 : :
3559 : : ! The preconditioned density/potential residual vrespc = P^-1 * vresid is computed
3560 : : ! by sovling the linear equation P * vrespc = vresid approximately with GMRES.
3561 : :
3562 : 18 : n = dtset%nspden*1*this%nfftprc
3563 : :
3564 : : !0.1) Convert the input to direct/real space if needed.
3565 [ - + ]: 18 : if (optreal==0) then
3566 : : ! vresid is given in the Fourier space : We need to do a ifft.
3567 [ # # # # : 0 : ABI_MALLOC(work_g, (2, this%nfftprc, dtset%nspden))
# # # # #
# # # # #
# # ]
3568 [ # # ]: 0 : work_g = reshape(vresid, (/2,this%nfftprc, dtset%nspden/))
3569 [ # # # # : 0 : call fourdp(1, work_g, vrespc(1:this%nfftprc, :), 1, mpi_enreg, this%nfftprc, dtset%nspden, this%ngfftprc, 0)
# # # # #
# # # #
# ]
3570 : : else
3571 [ + + + + ]: 121554 : vrespc = vresid
3572 : : end if
3573 : :
3574 : : !0.2) Convert the input to the Pauli basis
3575 : 18 : call to_pauli(optres, vrespc)
3576 : :
3577 : : !1) Right-hand side : rhs is vresid (flattened) in the direct/real space.
3578 [ - + + - : 54 : ABI_MALLOC(rhs, (n))
+ - + - -
+ - + ]
3579 [ + + ]: 54 : do ispden = 1, dtset%nspden
3580 : : ! Indices of the ispden component in the flattened (this%nfftprc, dtset%nspden)-array 'rhs'.
3581 : 36 : start_ispden = 1+(ispden-1)*this%nfftprc
3582 : 36 : end_ispden = ispden*this%nfftprc
3583 [ + + ]: 121554 : rhs(start_ispden:end_ispden) = vrespc(1:this%nfftprc, ispden)
3584 : : end do
3585 : :
3586 : : !2) Initial guess :
3587 [ - + + - : 36 : ABI_MALLOC(est, (n))
- + - + ]
3588 [ + + ]: 121518 : est = 0
3589 : : ! Is est = rhs a better starting point ?
3590 : : !est = rhs
3591 : :
3592 : : !3) Resolution of the linear system :
3593 [ - + ]: 18 : if (this%precon_verbose>0) call wrtout(std_out, '-- chi0-based preconditioning - Linear Solver --')
3594 [ - + ]: 18 : if (this%use_ridgereg) then
3595 : : ! P is ill-conditionned :
3596 : : ! Ridge/Tikhonov regularization and CG :
3597 : : ! We solve (P^*P + ridge_param*I) * est = P * rhs
3598 : : ! (P^*P + ridge_param*I) is self-adjoint and can be solved with CG.
3599 [ # # # # : 0 : ABI_MALLOC(P_rhs, (n))
# # # # ]
3600 : 0 : call ridge_matvec(n, rhs, P_rhs)
3601 : 0 : call cg_linear_solver(n, ridge_matvec, P_rhs, est, (this%linsolve_maxiter-1)/2+1, this%linsolve_rtol, this%precon_verbose>0)
3602 [ # # ]: 0 : ABI_FREE(P_rhs)
3603 : : else
3604 : : ! P is well conditionned :
3605 : : ! GMRES (P is not self-adjoint)
3606 : 18 : call gmres_linear_solver(n, matvec, rhs, est, this%linsolve_maxiter, this%linsolve_rtol, this%precon_verbose>0)
3607 : :
3608 : : end if
3609 : :
3610 : : !4.0) Free arrays that might have been allocated by precon_update
3611 : 18 : call precon_free_update(this)
3612 : :
3613 : : !4) Reshaping the final result :
3614 [ + + ]: 54 : do ispden = 1, dtset%nspden
3615 : : ! Indices of the ispden component in the flattened (this%nfftprc, dtset%nspden)-array 'est'.
3616 : 36 : start_ispden = 1+(ispden-1)*this%nfftprc
3617 : 36 : end_ispden = ispden*this%nfftprc
3618 [ + - ]: 54 : if (optreal==1) then
3619 : : ! vrespc must be returned in the direct/real space.
3620 [ + + ]: 121536 : vrespc(:, ispden) = est(start_ispden:end_ispden)
3621 : : else
3622 : : ! vrespc must be returned in the fourier space, we need to do a fft.
3623 : 0 : call fourdp(1, work_g, est(start_ispden:end_ispden), -1, mpi_enreg, this%nfftprc, 1, this%ngfftprc, 0)
3624 [ # # ]: 0 : vrespc(:, ispden) = reshape(work_g, (/2*this%nfftprc/))
3625 : : end if
3626 : : end do
3627 : : ! vrespc must be returned in the default Abinit spin-basis.
3628 : 18 : call from_pauli(optres, vrespc)
3629 : :
3630 [ - + ]: 18 : ABI_FREE(rhs)
3631 [ - + ]: 18 : ABI_FREE(est)
3632 : :
3633 : : end if
3634 : :
3635 : : contains
3636 : :
3637 : : ! Subroutine matvec that applies the model (adjoint-) dielectric matrix. -----------
3638 : 90 : subroutine matvec(n_, x, y)
3639 : : integer, intent(in) :: n_
3640 : : real(dp), intent(inout), target :: x(n_), y(n_)
3641 : : type(c_ptr) :: x_c, y_c
3642 : 90 : real(dp), pointer :: x_2d(:, :), y_2d(:, :)
3643 : :
3644 : : ! **********************************************************************************
3645 : :
3646 : : ! C-pointers to match the flattened arrays x and y to their 3D versions needed by
3647 : : ! 'apply_adjdielmat' and 'apply_dielmat'.
3648 : 90 : x_c = c_loc(x)
3649 [ + + ]: 270 : call c_f_pointer(x_c, x_2d, shape=[this%nfftprc, dtset%nspden])
3650 : 90 : y_c = c_loc(y)
3651 [ + + ]: 270 : call c_f_pointer(y_c, y_2d, shape=[this%nfftprc, dtset%nspden])
3652 : :
3653 [ + - ]: 90 : if (optres==1) then
3654 : : ! We are preconditioning density residual so P models the adjoint dielectric matrix.
3655 [ - + - + ]: 90 : call this%apply_adjdielmat(dtset, mpi_enreg, x_2d, y_2d)
3656 [ # # ]: 0 : else if (optres==0) then
3657 : : ! We are preconditioning potential residual so P models the dielectric matrix.
3658 [ # # # # ]: 0 : call this%apply_dielmat(dtset, mpi_enreg, x_2d, y_2d)
3659 : : end if
3660 : :
3661 : 90 : end subroutine matvec ! ------------------------------------------------------------
3662 : :
3663 : : ! Subroutine ridge_matvec that applies the operator (P^*P + ridge_param*I) needed for ridge regularization.
3664 : 0 : subroutine ridge_matvec(n_, x, y)
3665 : : integer, intent(in) :: n_
3666 : : real(dp), intent(inout), target :: x(n_), y(n_)
3667 : : type(c_ptr) :: x_c, y_c
3668 : 0 : real(dp), pointer :: x_2d(:, :), y_2d(:, :), temp_2d(:, :)
3669 : :
3670 : : ! **********************************************************************************
3671 : :
3672 : : ! C pointers to match the flattened arrays x and y to their 3D versions needed by
3673 : : ! 'apply_adjdielmat' and 'apply_dielmat'.
3674 : 0 : x_c = c_loc(x)
3675 [ # # ]: 0 : call c_f_pointer(x_c, x_2d, shape=[this%nfftprc, dtset%nspden])
3676 : 0 : y_c = c_loc(y)
3677 [ # # ]: 0 : call c_f_pointer(y_c, y_2d, shape=[this%nfftprc, dtset%nspden])
3678 [ # # # # : 0 : ABI_MALLOC(temp_2d, (this%nfftprc, dtset%nspden)) ! Temporary array for intermediate result
# # # # #
# # # # #
# # ]
3679 : :
3680 [ # # ]: 0 : if (optres==1) then
3681 : : ! We are preconditioning density residual so P models the adjoint dielectric matrix.
3682 [ # # # # ]: 0 : call this%apply_adjdielmat(dtset, mpi_enreg, x_2d, temp_2d)
3683 [ # # # # ]: 0 : call this%apply_dielmat(dtset, mpi_enreg, temp_2d, y_2d)
3684 [ # # ]: 0 : else if (optres==0) then
3685 : : ! We are preconditioning potential residual so P models the dielectric matrix.
3686 [ # # # # ]: 0 : call this%apply_dielmat(dtset, mpi_enreg, x_2d, temp_2d)
3687 [ # # # # ]: 0 : call this%apply_adjdielmat(dtset, mpi_enreg, temp_2d, y_2d)
3688 : : end if
3689 [ # # # # : 0 : y_2d = y_2d + this%ridge_param*x_2d
# # # # #
# ]
3690 [ # # ]: 0 : ABI_FREE(temp_2d)
3691 : :
3692 : 0 : end subroutine ridge_matvec ! ---------------------------------------------------------
3693 : :
3694 : : end subroutine apply_precon
3695 : :
3696 [ - + - - : 324519 : end module m_precon
+ + - + +
- - + - +
+ - - + -
+ - + - +
- + - + ]
|