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-09-20 15:27:41 Functions: 73.2 % 41 30

            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        20754 :     subroutine precon_init(this, dtset, atindx, atindx1, cg, cprj, dimcprj, dtfil, eigen, fermie, &
     181        20754 :         &   gmet, gprimd, indsym, irrzon, kg, mcprj, nattyp, nfftmix, ngfftmix, npwarr, occ, pawang, pawfgr, pawfgrtab, &
     182        20754 :         &   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         6918 :         this%iprcel = dtset%iprcel
     215         6918 :         this%use_precon = .false.
     216         6918 :         this%use_kxc = .false.
     217              : 
     218         6918 :         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         6918 :     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         6918 :     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         6918 :         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         6918 :     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         6918 :     subroutine precon_free(this)
     501              : 
     502              :         !Arguments ------------------------------------
     503              :         class(precon_object), intent(inout) :: this
     504              : 
     505              :         ! *************************************************************************
     506         6918 :         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         6918 :     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       324414 : end module m_precon
        

Generated by: LCOV version 2.3-1