LCOV - code coverage report
Current view: top level - src/68_rsprc - m_precon.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 50.0 % 1031 516
Test Date: 2026-11-10 13:31:01 Functions: 73.2 % 41 30
Branches: 21.8 % 3176 693

             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
          +  +  -  +  +  
          -  -  +  -  +  
          +  -  -  +  -  
          +  -  +  -  +  
             -  +  -  + ]
        

Generated by: LCOV version 2.3-1