LCOV - code coverage report
Current view: top level - src/70_gw - m_gwls_DielectricArray.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.8 % 748 612
Test Date: 2026-09-21 22:40:37 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !!****m* ABINIT/m_gwls_DielectricArray
       2              : !! NAME
       3              : !! m_gwls_DielectricArray
       4              : !!
       5              : !! FUNCTION
       6              : !!  .
       7              : !!
       8              : !! COPYRIGHT
       9              : !! Copyright (C) 2009-2026 ABINIT group (JLJ, BR, MC)
      10              : !! This file is distributed under the terms of the
      11              : !! GNU General Public License, see ~abinit/COPYING
      12              : !! or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : 
      23              : module m_gwls_DielectricArray
      24              : !----------------------------------------------------------------------------------------------------
      25              : ! This module generates and stores the arrays
      26              : !
      27              : !        { eps^{-1}(iw)-eps_model^{-1}(iw) }  in Lanczos basis
      28              : !        { eps_model^{-1}(iw) - 1 }           in model Lanczos basis
      29              : !
      30              : ! It makes sense to build these only once, as they do not depend on the external frequency.
      31              : !
      32              : !----------------------------------------------------------------------------------------------------
      33              : 
      34              : ! local modules
      35              : use m_gwls_utility
      36              : use m_gwls_wf
      37              : use m_gwls_valenceWavefunctions
      38              : use m_gwls_hamiltonian
      39              : use m_gwls_lineqsolver
      40              : use m_gwls_polarisability
      41              : use m_gwls_model_polarisability
      42              : use m_gwls_GenerateEpsilon
      43              : use m_gwls_TimingLog
      44              : use m_gwls_QR_factorization
      45              : use m_gwls_LanczosBasis
      46              : 
      47              : ! abinit modules
      48              : use defs_basis
      49              : use m_abicore
      50              : use m_xmpi
      51              : use m_cgtools
      52              : 
      53              : use m_time,                only : timab
      54              : use m_io_tools,            only: get_unit
      55              : use m_gaussian_quadrature, only: get_frequencies_and_weights_legendre
      56              : 
      57              : 
      58              : implicit none
      59              : save
      60              : 
      61              : private
      62              : !!***
      63              : 
      64              : ! Frequencies and weights for Legendre integration
      65              : real(dp), public, allocatable :: list_omega(:)
      66              : real(dp), public, allocatable :: list_weights(:)
      67              : 
      68              : ! Arrays to store the combinations of dielectric operators
      69              : complex(dp), public, allocatable :: model_dielectric_Lanczos_basis(:,:,:)
      70              : complex(dp), public, allocatable :: projected_dielectric_Lanczos_basis(:,:,:)
      71              : complex(dp), public, allocatable :: eps_m1_minus_eps_model_m1(:,:,:)
      72              : 
      73              : complex(dp), public, allocatable :: eps_model_m1_minus_one(:,:,:)
      74              : complex(dp),public, allocatable :: eps_model_m1_minus_one_DISTR(:,:,:)
      75              : 
      76              : 
      77              : ! dimensions of blocks in the model dielectric matrix
      78              : integer,public :: nbdblock_epsilon
      79              : integer,public :: blocksize_epsilon
      80              : logical,public, allocatable :: model_lanczos_vector_belongs_to_this_node(:)
      81              : integer,public, allocatable :: model_lanczos_vector_index(:)
      82              : 
      83              : 
      84              : ! Arrays necessary to project the Sternheimer equation within
      85              : ! the computation of the dielectric matrix.
      86              : complex(dp), public, allocatable :: projected_epsilon_M_matrix(:,:,:)
      87              : complex(dp), public, allocatable :: projected_epsilon_B_matrix(:,:,:)
      88              : complex(dp), public, allocatable :: projected_epsilon_G_matrix(:,:,:)
      89              : 
      90              : integer,public, allocatable  :: list_lsolutions_EpsilonProjected(:)
      91              : !!***
      92              : 
      93              : public :: generate_frequencies_and_weights
      94              : public :: cleanup_projected_Sternheimer_epsilon
      95              : public :: compute_eps_m1_minus_eps_model_m1
      96              : public :: compute_eps_m1_minus_one
      97              : public :: compute_eps_model_m1_minus_one
      98              : public :: ProjectedSternheimerEpsilon
      99              : !!***
     100              : 
     101              : contains
     102              : 
     103              : !!****f* m_hamiltonian/generate_frequencies_and_weights
     104              : !! NAME
     105              : !!  generate_frequencies_and_weights
     106              : !!
     107              : !! FUNCTION
     108              : !!  .
     109              : !!
     110              : !! INPUTS
     111              : !!
     112              : !! OUTPUT
     113              : !!
     114              : !! SOURCE
     115              : 
     116            7 : subroutine generate_frequencies_and_weights(npt_gauss)
     117              : !--------------------------------------------------------------------------------
     118              : !
     119              : ! This subroutine computes the frequencies and weights necessary for Gauss-Legendre
     120              : ! quadrature, and stores the results in module arrays.
     121              : !
     122              : !--------------------------------------------------------------------------------
     123              : integer, intent(in)  :: npt_gauss
     124              : 
     125              : 
     126            7 : real(dp), allocatable ::   list_omega_tmp(:)
     127            7 : real(dp), allocatable :: list_weights_tmp(:)
     128              : 
     129              : integer     :: i
     130              : 
     131              : ! *************************************************************************
     132              : 
     133           21 : ABI_MALLOC(list_omega_tmp,   (npt_gauss))
     134           14 : ABI_MALLOC(list_weights_tmp, (npt_gauss))
     135              : 
     136            7 : call get_frequencies_and_weights_legendre(npt_gauss,list_omega_tmp,list_weights_tmp)
     137              : 
     138              : 
     139           21 : ABI_MALLOC(list_omega,   (npt_gauss+1))
     140           14 : ABI_MALLOC(list_weights, (npt_gauss+1))
     141              : 
     142              : ! make sure the first frequency in zero!
     143            7 : list_omega(1)   = zero
     144            7 : list_weights(1) = zero
     145              : 
     146           77 : do i = 1,npt_gauss
     147              : 
     148              : ! inverse the order of the frequency points, as they come out
     149              : ! in reverse order from the generating subroutine
     150           70 : list_omega  (i+1) = list_omega_tmp  (npt_gauss+1-i)
     151           77 : list_weights(i+1) = list_weights_tmp(npt_gauss+1-i)
     152              : 
     153              : end do
     154              : 
     155              : 
     156            7 : ABI_FREE(list_omega_tmp)
     157            7 : ABI_FREE(list_weights_tmp)
     158              : 
     159              : 
     160            7 : end subroutine generate_frequencies_and_weights
     161              : !!***
     162              : 
     163              : !!****f* m_hamiltonian/compute_eps_m1_minus_eps_model_m1
     164              : !! NAME
     165              : !!  compute_eps_m1_minus_eps_model_m1
     166              : !!
     167              : !! FUNCTION
     168              : !!  .
     169              : !!
     170              : !! INPUTS
     171              : !!
     172              : !! OUTPUT
     173              : !!
     174              : !! SOURCE
     175              : 
     176            6 : subroutine compute_eps_m1_minus_eps_model_m1(lmax, npt_gauss)
     177              : !----------------------------------------------------------------------------------------------------
     178              : !
     179              : ! This subroutine computes the array
     180              : !
     181              : !                eps^{-1}(iw) - eps_model^{-1}(iw),
     182              : !
     183              : ! for all relevant frequencies in the Lanczos basis.
     184              : !----------------------------------------------------------------------------------------------------
     185              : integer ,     intent(in)  :: lmax, npt_gauss
     186              : 
     187              : character(256) :: timing_string
     188              : real(dp)       :: time1, time2
     189              : real(dp)       :: time
     190              : 
     191              : integer        :: iw, l
     192            6 : complex(dp),allocatable  :: dummy_matrix(:,:)
     193            6 : complex(dp),allocatable  :: iden(:,:)
     194              : ! *************************************************************************
     195              : 
     196            6 : timing_string = "#"
     197            6 : call write_text_block_in_Timing_log(timing_string)
     198            6 : timing_string = "#        Computing eps^{-1}(iw) - eps_model^{-1}(iw) "
     199            6 : call write_text_block_in_Timing_log(timing_string)
     200            6 : timing_string = "#"
     201            6 : call write_text_block_in_Timing_log(timing_string)
     202              : 
     203              : 
     204            6 : call cpu_time(time1)
     205              : ! Allocate the module array
     206           30 : ABI_MALLOC(eps_m1_minus_eps_model_m1, (lmax,lmax,npt_gauss+1))
     207           24 : ABI_MALLOC(dummy_matrix, (lmax,lmax))
     208           18 : ABI_MALLOC(iden, (lmax,lmax))
     209              : 
     210              : 
     211          438 : iden = cmplx_0
     212              : 
     213           54 : do l = 1, lmax
     214           54 : iden(l,l) = cmplx_1
     215              : end do
     216              : 
     217           72 : do iw = 1, npt_gauss + 1
     218              : 
     219              : 
     220         4818 : dummy_matrix(:,:) = projected_dielectric_Lanczos_basis(:,:,iw)
     221              : 
     222           66 : call driver_invert_positive_definite_hermitian_matrix(dummy_matrix,lmax)
     223              : 
     224              : 
     225         4818 : eps_m1_minus_eps_model_m1(:,:,iw) = dummy_matrix(:,:)
     226              : 
     227         4818 : dummy_matrix(:,:) = model_dielectric_Lanczos_basis(:,:,iw)
     228              : 
     229              : 
     230              : 
     231           66 : call driver_invert_positive_definite_hermitian_matrix(dummy_matrix,lmax)
     232              : 
     233         4824 : eps_m1_minus_eps_model_m1(:,:,iw) = eps_m1_minus_eps_model_m1(:,:,iw) - dummy_matrix(:,:)
     234              : 
     235              : 
     236              : end do
     237              : 
     238              : 
     239              : 
     240              : 
     241              : ! Deallocate the arrays which are no longer needed
     242            6 : ABI_FREE(model_dielectric_Lanczos_basis)
     243            6 : ABI_FREE(projected_dielectric_Lanczos_basis)
     244              : 
     245              : 
     246              : 
     247            6 : ABI_FREE(dummy_matrix)
     248            6 : ABI_FREE(iden)
     249              : 
     250              : 
     251              : 
     252            6 : call cpu_time(time2)
     253            6 : time = time2-time1
     254              : 
     255            6 : timing_string = "#        Total time   :   "
     256            6 : call write_timing_log(timing_string,time)
     257              : 
     258              : 
     259              : 
     260              : 
     261            6 : end subroutine compute_eps_m1_minus_eps_model_m1
     262              : !!***
     263              : 
     264              : !!****f* m_hamiltonian/compute_eps_m1_minus_one
     265              : !! NAME
     266              : !!  compute_eps_m1_minus_one
     267              : !!
     268              : !! FUNCTION
     269              : !!  .
     270              : !!
     271              : !! INPUTS
     272              : !!
     273              : !! OUTPUT
     274              : !!
     275              : !! SOURCE
     276              : 
     277            1 : subroutine compute_eps_m1_minus_one(lmax, npt_gauss)
     278              : !----------------------------------------------------------------------------------------------------
     279              : !
     280              : ! This subroutine computes the array
     281              : !
     282              : !                eps^{-1}(iw) - I
     283              : !
     284              : ! for all relevant frequencies in the Lanczos basis.
     285              : !----------------------------------------------------------------------------------------------------
     286              : integer ,     intent(in)  :: lmax, npt_gauss
     287              : 
     288              : character(256) :: timing_string
     289              : real(dp)       :: time1, time2
     290              : real(dp)       :: time
     291              : 
     292              : integer        :: iw, l
     293            1 : complex(dp),allocatable  :: dummy_matrix(:,:)
     294            1 : complex(dp),allocatable  :: iden(:,:)
     295              : ! *************************************************************************
     296              : 
     297            1 : timing_string = "#"
     298            1 : call write_text_block_in_Timing_log(timing_string)
     299            1 : timing_string = "#        Computing eps^{-1}(iw) - I "
     300            1 : call write_text_block_in_Timing_log(timing_string)
     301            1 : timing_string = "#"
     302            1 : call write_text_block_in_Timing_log(timing_string)
     303              : 
     304            1 : call cpu_time(time1)
     305              : ! Allocate the module array
     306              : 
     307              : ! The array eps_m1_minus_eps_model_m1 will be used to store
     308              : ! eps^{-1}-1; we can think of eps_model = I in this case.
     309            5 : ABI_MALLOC(eps_m1_minus_eps_model_m1, (lmax,lmax,npt_gauss+1))
     310              : 
     311            4 : ABI_MALLOC(dummy_matrix, (lmax,lmax))
     312            3 : ABI_MALLOC(iden, (lmax,lmax))
     313              : 
     314           73 : iden = cmplx_0
     315              : 
     316            9 : do l = 1, lmax
     317            9 : iden(l,l) = cmplx_1
     318              : end do
     319              : 
     320              : 
     321           12 : do iw = 1, npt_gauss + 1
     322              : 
     323          803 : dummy_matrix(:,:) = projected_dielectric_Lanczos_basis(:,:,iw)
     324              : 
     325           11 : call driver_invert_positive_definite_hermitian_matrix(dummy_matrix,lmax)
     326              : 
     327          804 : eps_m1_minus_eps_model_m1(:,:,iw) = dummy_matrix(:,:)-iden(:,:)
     328              : 
     329              : end do
     330              : 
     331              : 
     332              : ! Deallocate the arrays which are no longer needed
     333            1 : ABI_FREE(projected_dielectric_Lanczos_basis)
     334              : 
     335            1 : ABI_FREE(dummy_matrix)
     336            1 : ABI_FREE(iden)
     337              : 
     338            1 : call cpu_time(time2)
     339            1 : time = time2-time1
     340              : 
     341            1 : timing_string = "#        Total time   :   "
     342            1 : call write_timing_log(timing_string,time)
     343              : 
     344            1 : end subroutine compute_eps_m1_minus_one
     345              : !!***
     346              : 
     347              : !!****f* m_hamiltonian/compute_eps_model_m1_minus_one
     348              : !! NAME
     349              : !!  compute_eps_model_m1_minus_one
     350              : !!
     351              : !! FUNCTION
     352              : !!  .
     353              : !!
     354              : !! INPUTS
     355              : !!
     356              : !! OUTPUT
     357              : !!
     358              : !! SOURCE
     359              : 
     360            6 : subroutine compute_eps_model_m1_minus_one(lmax_model, npt_gauss, second_model_parameter, epsilon_model_eigenvalues_0)
     361              : !----------------------------------------------------------------------------------------------------
     362              : !
     363              : ! This subroutine computes the array
     364              : !
     365              : !                eps_model^{-1}(iw) - 1
     366              : !
     367              : ! for all relevant frequencies in the model Lanczos basis.
     368              : !
     369              : ! This array can potentially get very large, as the complementary basis gets big to achieve
     370              : ! convergence. Correspondingly, it makes sense to DISTRIBUTE this array on all processors.
     371              : !
     372              : ! The algorithm will go as follows:
     373              : !
     374              : !               eps_m = 1 - V . P . V, V = sqrt{vc}
     375              : !
     376              : !       I ) compute VPV, storing blocks on different processors:
     377              : !
     378              : !               VPV = [ ------- --------      ]  = VPV[lc, nB, nW]
     379              : !                  |  [| block |  block |     ]
     380              : !                 lc  [|   1   |    2   | ... ]
     381              : !                  |  [|       |        |     ]
     382              : !                  |  [|       |        |     ]
     383              : !                  |  [ ------- ---------     ]
     384              : !                        bsize
     385              : !
     386              : !               This construction *does* involve a fair bit of communications, but it takes
     387              : !               a lot less RAM!
     388              : !
     389              : !       II) once VPV is constructed, do, one frequency at a time:
     390              : !               - import all blocks to the HEAD processor
     391              : !               - compute eps_m = 1- VPV
     392              : !               - invert eps_m^{-1}
     393              : !               - subtract identity eps_m^{-1} - 1
     394              : !               - redistribute, block by block
     395              : !
     396              : !               Doing this frequency by frequency will reduce the RAM weight on the head node.
     397              : !
     398              : !
     399              : !----------------------------------------------------------------------------------------------------
     400              : integer,  intent(in) :: lmax_model, npt_gauss
     401              : real(dp), intent(in) :: second_model_parameter
     402              : real(dp), intent(in) :: epsilon_model_eigenvalues_0(lmax_model)
     403              : 
     404              : integer  :: l, l1, l2
     405              : integer  :: iw
     406              : integer  :: v
     407              : integer  :: ierr
     408              : 
     409            6 : real(dp),    allocatable :: psikg_valence(:,:)
     410            6 : real(dp),    allocatable :: psir_valence(:,:,:,:)
     411              : 
     412              : 
     413            6 : real(dp),    allocatable :: psik_wrk(:,:)
     414            6 : real(dp),    allocatable :: psikb_wrk(:,:)
     415            6 : real(dp),    allocatable :: psikg_wrk(:,:)
     416            6 : real(dp),    allocatable :: psikg_tmp(:,:)
     417              : 
     418            6 : complex(dp),allocatable :: local_Lbasis_conjugated(:,:)
     419              : 
     420              : 
     421            6 : complex(dp),allocatable :: VPV(:,:,:)
     422            6 : real(dp),    allocatable :: re_buffer(:,:), im_buffer(:,:)
     423              : 
     424            6 : complex(dp),allocatable :: vpv_row(:)
     425              : 
     426              : 
     427            6 : complex(dp),allocatable :: epsilon_head(:,:)
     428              : 
     429            6 : real(dp), allocatable :: re_BUFFER_head(:,:)
     430            6 : real(dp), allocatable :: im_BUFFER_head(:,:)
     431              : 
     432              : 
     433              : 
     434            6 : complex(dp),allocatable :: YL(:)
     435              : 
     436              : character(256) :: timing_string
     437              : real(dp)       :: time1, time2, time
     438              : real(dp)       :: fft_time1, fft_time2, fft_time
     439              : real(dp)       :: prod_time1, prod_time2, prod_time
     440              : 
     441              : complex(dp)   :: z
     442              : 
     443              : 
     444              : integer   :: iblk_lanczos, nbdblock_lanczos
     445              : integer   :: mb
     446              : integer   :: lb
     447              : integer   :: ik
     448              : 
     449              : integer   :: mpi_communicator
     450              : integer   :: mpi_nproc
     451              : integer   :: mpi_rank
     452              : integer   :: mpi_head_rank
     453              : 
     454              : 
     455            6 : integer,allocatable   :: sendcounts(:), displs(:)
     456              : 
     457              : integer   :: sendcount, recvcount
     458              : 
     459              : 
     460              : logical   :: head
     461              : 
     462              : 
     463              : ! timing
     464              : real(dp) :: tsec(2)
     465              : integer :: GWLS_TIMAB, OPTION_TIMAB
     466              : 
     467              : ! *************************************************************************
     468              : 
     469              : 
     470            6 : GWLS_TIMAB   = 1541
     471            6 : OPTION_TIMAB = 1
     472            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     473              : 
     474              : 
     475              : 
     476            6 : timing_string = "#"
     477            6 : call write_text_block_in_Timing_log(timing_string)
     478            6 : timing_string = "#        computing eps_model_m1_minus_one"
     479            6 : call write_text_block_in_Timing_log(timing_string)
     480            6 : timing_string = "#"
     481            6 : call write_text_block_in_Timing_log(timing_string)
     482              : 
     483              : 
     484              : ! Number of blocks of lanczos vectors (blocksize = npband)
     485            6 : nbdblock_lanczos = lmax_model/blocksize
     486            6 : if (modulo(lmax_model,blocksize) /= 0) nbdblock_lanczos = nbdblock_lanczos + 1
     487              : 
     488              : 
     489              : ! communicator
     490            6 : mpi_communicator = mpi_enreg%comm_bandfft
     491              : 
     492              : ! total number of processors in the communicator
     493            6 : mpi_nproc        = xmpi_comm_size(mpi_communicator )
     494              : 
     495              : ! what is the rank of this processor?
     496            6 : mpi_rank         = xmpi_comm_rank(mpi_communicator )
     497              : 
     498              : ! rank of the "head" processor
     499            6 : mpi_head_rank    = 0
     500              : 
     501              : 
     502              : ! number of blocks in the model dielectric matrix, which is equal to the number of processors
     503            6 : nbdblock_epsilon = mpi_nproc
     504              : 
     505              : 
     506              : ! number of vectors in every block
     507            6 : blocksize_epsilon =  lmax_model/mpi_nproc
     508            6 : if (modulo(lmax_model,mpi_nproc) /= 0) blocksize_epsilon = blocksize_epsilon + 1
     509              : 
     510              : ! attribute blocks to every nodes, and tabulate ownership in logical array
     511              : ! This is not *the most efficient* implementation possible, but it is convenient
     512           18 : ABI_MALLOC( model_lanczos_vector_belongs_to_this_node, (lmax_model))
     513           12 : ABI_MALLOC( model_lanczos_vector_index, (lmax_model))
     514              : 
     515              : 
     516           54 : model_lanczos_vector_index = 0
     517           54 : model_lanczos_vector_belongs_to_this_node = .false.
     518              : 
     519           54 : do l =1, lmax_model
     520           54 : if (mpi_rank == (l-1)/blocksize_epsilon) then
     521           24 :   model_lanczos_vector_belongs_to_this_node(l) = .true.
     522           24 :   model_lanczos_vector_index(l) = l-mpi_rank*blocksize_epsilon
     523              : end if
     524              : end do
     525              : 
     526              : !write(100+mpi_rank,*) "model_lanczos_vector_belongs_to_this_node = ",model_lanczos_vector_belongs_to_this_node(:)
     527              : !write(100+mpi_rank,*) "model_lanczos_vector_index                = ",model_lanczos_vector_index(:)
     528              : !flush(100+mpi_rank)
     529              : 
     530              : ! Prepare the array that will contain the matrix elements of the model operator
     531           30 : ABI_MALLOC(VPV, (lmax_model,blocksize_epsilon,npt_gauss+1))
     532              : 
     533         2448 : VPV(:,:,:) = cmplx_0
     534              : 
     535           18 : ABI_MALLOC(vpv_row, (lmax_model))
     536              : 
     537              : 
     538              : ! various working arrays
     539            6 : GWLS_TIMAB   = 1542
     540              : OPTION_TIMAB = 1
     541            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     542              : 
     543           18 : ABI_MALLOC(psikg_valence,(2,npw_g))
     544           30 : ABI_MALLOC(psir_valence ,(2,n4,n5,n6))
     545              : 
     546              : 
     547           18 : ABI_MALLOC(psik_wrk,  (2,npw_k))
     548           18 : ABI_MALLOC(psikb_wrk, (2,npw_kb))
     549           12 : ABI_MALLOC(psikg_wrk, (2,npw_g))
     550           12 : ABI_MALLOC(psikg_tmp, (2,npw_g))
     551              : 
     552           24 : ABI_MALLOC(local_Lbasis_conjugated,(npw_k,lmax_model))
     553           18 : ABI_MALLOC(YL,(npw_k))
     554              : 
     555            6 : OPTION_TIMAB = 2
     556            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     557              : 
     558              : 
     559              : 
     560            6 : fft_time  = zero
     561            6 : prod_time = zero
     562              : 
     563              : 
     564            6 : call cpu_time(time1)
     565              : ! loop on all valence bands
     566              : 
     567           30 : do v = 1, nbandv
     568              : 
     569              : 
     570              : ! copy pre-calculated valence state in this covenient local array
     571        12360 : psikg_valence(:,:) = kernel_wavefunctions_FFT(:,:,v)
     572              : 
     573              : ! compute fourier transform of valence state, and conjugate
     574           24 : call g_to_r(psir_valence,psikg_valence)
     575       164616 : psir_valence(2,:,:,:) = -psir_valence(2,:,:,:)
     576              : 
     577              : !--------------------------------------------------------------------------
     578              : !
     579              : ! Step 1: build the modified basis Pc . [ (V^{1/2} l) . psi_v^*].
     580              : !
     581              : !--------------------------------------------------------------------------
     582           24 : GWLS_TIMAB   = 1543
     583           24 : OPTION_TIMAB = 1
     584           24 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     585              : 
     586              : ! loop on all blocks of lanczos vectors
     587          152 : do iblk_lanczos = 1, nbdblock_lanczos
     588              : ! loop on all states within this block
     589          320 : do mb = 1, blocksize
     590              : 
     591              : ! Determine the index of the Lanczos vector
     592          192 : l = (iblk_lanczos-1)*blocksize + mb
     593              : 
     594          192 : if ( l <= lmax_model) then
     595        24864 :   psik_wrk(1,:) = dble (Lbasis_model_lanczos(:,l))
     596        24864 :   psik_wrk(2,:) = dimag(Lbasis_model_lanczos(:,l))
     597              : else
     598            0 :   psik_wrk(:,:) = zero
     599              : end if
     600              : 
     601              : ! apply Coulomb potential
     602          192 : call sqrt_vc_k(psik_wrk)
     603              : 
     604              : ! Store in array of blocks of wavefunctions
     605        74336 : psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k) = psik_wrk(:,:)
     606              : 
     607              : end do ! mb
     608              : 
     609          128 : call cpu_time(fft_time1)
     610              : 
     611              : ! Transform to FFT representation
     612          128 : call wf_block_distribute(psikb_wrk,  psikg_wrk,1) ! LA -> FFT
     613              : 
     614              : 
     615              : !  generate the vector  Pc [ (sqrt_V_c.l) psi_v^*]
     616              : 
     617              : ! Compute the real space product, and return to k space, in FFT configuration
     618          128 : call gr_to_g(psikg_tmp,psir_valence, psikg_wrk)
     619              : 
     620              : 
     621          128 : call cpu_time(fft_time2)
     622          128 : fft_time = fft_time + fft_time2-fft_time1
     623              : 
     624              : ! project
     625          128 : call pc_k_valence_kernel(psikg_tmp)
     626              : 
     627              : ! Return to LA configuration
     628              : 
     629              : ! Transform to FFT representation
     630          128 : call wf_block_distribute(psikb_wrk,  psikg_tmp, 2) ! FFT -> LA
     631              : 
     632          344 : do mb = 1, blocksize
     633              : 
     634              : ! Determine the index of the Lanczos vector
     635          192 : l = (iblk_lanczos-1)*blocksize + mb
     636              : 
     637              : 
     638          320 : if ( l <= lmax_model) then
     639        74208 :   psik_wrk(:,:) = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
     640        24864 :   local_Lbasis_conjugated(:,l) = cmplx_1*psik_wrk(1,:)+cmplx_i*psik_wrk(2,:)
     641              : end if
     642              : 
     643              : 
     644              : end do ! mb
     645              : 
     646              : end do !iblk_lanczos
     647           24 : OPTION_TIMAB = 2
     648           24 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     649              : 
     650              : 
     651              : !--------------------------------------------------------------------------
     652              : ! Step 2: Now that we have the modified basis, compute the matrix
     653              : !             elements of the model dielectric operator
     654              : !
     655              : !
     656              : !--------------------------------------------------------------------------
     657           24 : GWLS_TIMAB   = 1544
     658           24 : OPTION_TIMAB = 1
     659           24 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     660              : 
     661          264 : do iw = 2, npt_gauss+1
     662              : 
     663          240 : call setup_Pk_model(list_omega(iw),second_model_parameter)
     664              : 
     665          240 : call cpu_time(prod_time1)
     666         2160 : do l1 = 1, lmax_model
     667              : 
     668              : ! Apply core function Y to left-vector; conjugate
     669       248640 : do ik = 1, npw_k
     670       248640 : YL(ik) = model_Y_LA(ik)*conjg(local_Lbasis_conjugated(ik,l1))
     671              : end do
     672              : 
     673              : ! Only compute lower diagonal part of matrix; epsilon is hermitian conjugate!
     674        17280 : vpv_row = cmplx_0
     675        10560 : do l2 = 1, l1
     676      1120800 : do ik = 1, npw_k
     677      1118880 : vpv_row(l2) = vpv_row(l2) + YL(ik)*local_Lbasis_conjugated(ik,l2)
     678              : end do
     679              : end do
     680              : 
     681              : ! the code below is twice as long!
     682              : !call ZGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY )
     683              : !call ZGEMV ( 'T', npw_k, lmax_model, cmplx_1, local_Lbasis_conjugated, npw_k, YL, 1, cmplx_0, vpv_row, 1)
     684              : 
     685              : !do l2 = 1, l1
     686              : !        eps_model_m1_minus_one(l1,l2,iw) = eps_model_m1_minus_one(l1,l2,iw)     &
     687              : !                       -complex_vector_product(YL, local_Lbasis_conjugated(:,l2),npw_k)
     688              : !end do
     689              : 
     690              : ! Sum on all processors, making sure all processors have the total vpv_row
     691         1920 : call xmpi_sum(vpv_row, mpi_communicator, ierr) ! sum on all processors for LA configuration
     692              : 
     693              : ! Each processor takes its slice!
     694        10800 : do l2 =1, l1
     695        10560 : if ( model_lanczos_vector_belongs_to_this_node(l2) ) then
     696         4320 :   lb = model_lanczos_vector_index(l2)
     697         4320 :   VPV(l1,lb,iw) = VPV(l1,lb,iw) + vpv_row(l2)
     698              : end if
     699              : end do
     700              : 
     701              : end do
     702          240 : call cpu_time(prod_time2)
     703              : 
     704          264 : prod_time = prod_time + prod_time2-prod_time1
     705              : 
     706              : end do ! iw
     707           24 : OPTION_TIMAB = 2
     708           30 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     709              : 
     710              : end do ! v
     711              : 
     712            6 : call cpu_time(time2)
     713              : 
     714            6 : time = time2-time1
     715            6 : timing_string = "#        computing VPV                          : "
     716            6 : call write_timing_log(timing_string,time)
     717              : 
     718            6 : timing_string = "#                --- of which is FFT transforms : "
     719            6 : call write_timing_log(timing_string,fft_time)
     720              : 
     721            6 : timing_string = "#                --- of which is products       : "
     722            6 : call write_timing_log(timing_string,prod_time)
     723              : 
     724              : 
     725              : 
     726              : 
     727              : 
     728            6 : GWLS_TIMAB   = 1542
     729            6 : OPTION_TIMAB = 1
     730            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     731            6 : ABI_FREE(local_Lbasis_conjugated)
     732            6 : ABI_FREE(YL)
     733            6 : ABI_FREE(psikg_valence)
     734            6 : ABI_FREE(psir_valence)
     735            6 : ABI_FREE(psik_wrk)
     736            6 : ABI_FREE(psikb_wrk)
     737            6 : ABI_FREE(psikg_wrk)
     738            6 : ABI_FREE(psikg_tmp)
     739            6 : ABI_FREE(vpv_row)
     740              : 
     741            6 : OPTION_TIMAB = 2
     742            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     743              : 
     744              : 
     745              : 
     746            6 : call cpu_time(time1)
     747            6 : GWLS_TIMAB   = 1547
     748            6 : OPTION_TIMAB = 1
     749            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     750              : 
     751              : 
     752              : !--------------------------------------------------------------------------------
     753              : !
     754              : !
     755              : ! Gather dielectric matrix on head node, invert, and re-distribute. This
     756              : ! Saves a lot of RAM, without needing the full machinery of ScaLAPACK.
     757              : !
     758              : !--------------------------------------------------------------------------------
     759              : 
     760              : 
     761           30 : ABI_MALLOC(eps_model_m1_minus_one_DISTR, (lmax_model,blocksize_epsilon,npt_gauss+1))
     762           24 : ABI_MALLOC(re_buffer, (lmax_model,blocksize_epsilon))
     763           18 : ABI_MALLOC(im_buffer, (lmax_model,blocksize_epsilon))
     764              : 
     765         2448 : eps_model_m1_minus_one_DISTR(:,:,:) = cmplx_0
     766              : 
     767              : ! Define the head node, which will invert the dielectric matrices
     768            6 : head = mpi_rank == mpi_head_rank
     769              : 
     770              : ! Amount of data received and sent
     771            6 : sendcount = lmax_model*blocksize_epsilon
     772            6 : recvcount = lmax_model*blocksize_epsilon
     773              : 
     774           18 : ABI_MALLOC(sendcounts,(mpi_nproc))
     775           12 : ABI_MALLOC(displs    ,(mpi_nproc))
     776           24 : sendcounts(:) = sendcount
     777              : 
     778           24 : do l =1, mpi_nproc
     779           24 : displs(l) = (l-1)*sendcount
     780              : end do
     781              : 
     782            6 : if (head) then
     783              :   ! build and invert the dielectric array
     784              :   ! careful!  lmax_model not necessarily equal to blocksize_epsilon*nbdblock_epsilon
     785           12 :   ABI_MALLOC(re_BUFFER_head, (lmax_model, blocksize_epsilon*nbdblock_epsilon))
     786            9 :   ABI_MALLOC(im_BUFFER_head, (lmax_model, blocksize_epsilon*nbdblock_epsilon))
     787           12 :   ABI_MALLOC(epsilon_head, (lmax_model, lmax_model))
     788              : else
     789              :   !This looks superfluous and it is on large number of systems, but sending these
     790              :   !unallocated in xmpi_scatterv caused 'cannot allocate memory' cryptic errors on
     791              :   !several parallel test farm computers (cronos_gcc46_paral, petrus_nag, inca_gcc44_sdebug)
     792            3 :   ABI_MALLOC(re_BUFFER_head, (1,1))
     793            3 :   ABI_MALLOC(im_BUFFER_head, (1,1))
     794            3 :   ABI_MALLOC(epsilon_head, (1,1))
     795              : end if
     796              : 
     797              : ! Do  one frequency at a time, to avoid overflowing the RAM
     798           72 : do iw = 1, npt_gauss+1
     799              : ! Gather, except for static case
     800           66 : if ( iw /=1 ) then
     801              :   ! Gather VPV on head node, for this frequency
     802         2220 :   call xmpi_gather(dble(VPV(:,:,iw)),  sendcount , re_BUFFER_head, recvcount, mpi_head_rank, mpi_communicator,ierr)
     803         2220 :   call xmpi_gather(dimag(VPV(:,:,iw)), sendcount , im_BUFFER_head, recvcount, mpi_head_rank, mpi_communicator,ierr)
     804              : end if
     805              : 
     806           66 : if ( head ) then
     807              : 
     808              :   ! fill the dielectric matrix
     809              : 
     810         2409 :   epsilon_head(:,:) = cmplx_0
     811           33 :   if (iw ==1) then
     812              :     ! STATIC CASE, diagonal matrix
     813           27 :     do l= 1, lmax_model
     814           27 :     epsilon_head(l,l) = cmplx_1/epsilon_model_eigenvalues_0(l)-cmplx_1
     815              :     end do
     816              : 
     817              :   else
     818              :     ! DYNAMIC CASE, compute
     819          270 :     do l1 =1, lmax_model
     820         1320 :     do l2 =1, l1
     821         1080 :     z = -cmplx_1*re_BUFFER_head(l1,l2)-cmplx_i*im_BUFFER_head(l1,l2)
     822         1080 :     epsilon_head(l1,l2) = z
     823         1320 :     epsilon_head(l2,l1) = conjg(z)
     824              :     end do
     825          270 :     epsilon_head(l1,l1) = epsilon_head(l1,l1) + cmplx_1
     826              :     end do
     827              : 
     828              :     ! invert the matrix
     829           30 :     call driver_invert_positive_definite_hermitian_matrix(epsilon_head,lmax_model)
     830              : 
     831              :     ! subtract identity
     832          270 :     do l =1, lmax_model
     833          270 :     epsilon_head(l,l) = epsilon_head(l,l) - cmplx_1
     834              :     end do
     835              :   end if
     836              : 
     837              :   ! copy in head buffer
     838         2409 :   re_BUFFER_head(:,:) = zero
     839         2409 :   im_BUFFER_head(:,:) = zero
     840          297 :   do l1 =1, lmax_model
     841         2409 :   do l2 =1, lmax_model
     842         2112 :   z = epsilon_head(l1,l2)
     843         2112 :   re_BUFFER_head(l1,l2) = dble(z)
     844         2376 :   im_BUFFER_head(l1,l2) = dimag(z)
     845              :   end do
     846              :   end do
     847              : 
     848              : end if
     849              : 
     850              : ! Scatter back the data on the head to all processors
     851           66 : call xmpi_scatterv(re_BUFFER_head, sendcounts, displs, re_buffer, recvcount, mpi_head_rank, mpi_communicator, ierr)
     852           66 : call xmpi_scatterv(im_BUFFER_head, sendcounts, displs, im_buffer, recvcount, mpi_head_rank, mpi_communicator, ierr)
     853              : 
     854         2448 : eps_model_m1_minus_one_DISTR(:,:,iw) = cmplx_1*re_buffer(:,:) + cmplx_i*im_buffer(:,:)
     855              : 
     856              : end do
     857              : 
     858            6 : ABI_FREE(re_BUFFER_head)
     859            6 : ABI_FREE(im_BUFFER_head)
     860            6 : ABI_FREE(epsilon_head)
     861              : 
     862              : 
     863              : 
     864              : !================================================================================
     865              : !
     866              : ! For debugging purposes, store distributed dielectric matrix back in the
     867              : ! complete local copies, to insure the rest of the code works.
     868              : !
     869              : !================================================================================
     870              : 
     871              : if (.false.) then
     872              :   ! Prepare the array that will contain the matrix elements of the model operator
     873              :   ! THIS IS ONLY FOR THE REST OF THE CODE TO WORK; WE WILL REMOVE THIS
     874              :   ! TO SAVE RAM LATER
     875              :   ABI_MALLOC(eps_model_m1_minus_one, (lmax_model,lmax_model,npt_gauss+1))
     876              : 
     877              :   ! initialize the array with zeros
     878              :   eps_model_m1_minus_one = cmplx_0
     879              : 
     880              :   ! Amount of data received and sent
     881              :   sendcount = lmax_model*blocksize_epsilon
     882              :   recvcount = lmax_model*blocksize_epsilon*nbdblock_epsilon
     883              : 
     884              : 
     885              :   ABI_MALLOC(re_BUFFER_head, (lmax_model,blocksize_epsilon*nbdblock_epsilon))
     886              :   ABI_MALLOC(im_BUFFER_head, (lmax_model,blocksize_epsilon*nbdblock_epsilon))
     887              : 
     888              :   do iw = 1, npt_gauss+1
     889              : 
     890              :   re_buffer(:,:) = dble( eps_model_m1_minus_one_DISTR(:,:,iw))
     891              :   im_buffer(:,:) = dimag(eps_model_m1_minus_one_DISTR(:,:,iw))
     892              : 
     893              :   call xmpi_allgather(re_buffer,sendcount,re_BUFFER_head,mpi_communicator,ierr)
     894              :   call xmpi_allgather(im_buffer,sendcount,im_BUFFER_head,mpi_communicator,ierr)
     895              : 
     896              :   do l = 1, lmax_model
     897              :   eps_model_m1_minus_one(:,l,iw) =  cmplx_1*re_BUFFER_head(:,l)+ cmplx_i*im_BUFFER_head(:,l)
     898              :   end do
     899              :   end do
     900              : 
     901              :   ABI_FREE(re_BUFFER_head)
     902              :   ABI_FREE(im_BUFFER_head)
     903              : end if
     904              : 
     905            6 : call cpu_time(time2)
     906            6 : OPTION_TIMAB = 2
     907            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     908              : 
     909              : !================================================================================
     910              : !
     911              : !================================================================================
     912              : 
     913              : 
     914            6 : time = time2-time1
     915            6 : timing_string = "#        inverting / distributing               :  "
     916              : 
     917            6 : call write_timing_log(timing_string,time)
     918              : 
     919              : 
     920              : 
     921            6 : ABI_FREE(re_buffer )
     922            6 : ABI_FREE(im_buffer )
     923            6 : ABI_FREE(sendcounts)
     924            6 : ABI_FREE(displs    )
     925            6 : ABI_FREE(VPV       )
     926              : 
     927              : 
     928              : 
     929            6 : GWLS_TIMAB   = 1541
     930              : OPTION_TIMAB = 2
     931            6 : call timab(GWLS_TIMAB,OPTION_TIMAB,tsec)
     932              : 
     933              : 
     934            6 : end subroutine compute_eps_model_m1_minus_one
     935              : !!***
     936              : 
     937              : !!****f* m_hamiltonian/cleanup_projected_Sternheimer_epsilon
     938              : !! NAME
     939              : !!  cleanup_projected_Sternheimer_epsilon
     940              : !!
     941              : !! FUNCTION
     942              : !!  .
     943              : !!
     944              : !! INPUTS
     945              : !!
     946              : !! OUTPUT
     947              : !!
     948              : !! SOURCE
     949              : 
     950            7 : subroutine cleanup_projected_Sternheimer_epsilon
     951              : 
     952              : ! *************************************************************************
     953              : 
     954            7 : ABI_SFREE(projected_epsilon_M_matrix)
     955            7 : ABI_SFREE(projected_epsilon_B_matrix)
     956            7 : ABI_SFREE(projected_epsilon_G_matrix)
     957            7 : ABI_SFREE(eps_m1_minus_eps_model_m1)
     958            7 : ABI_SFREE(list_omega)
     959            7 : ABI_SFREE(list_weights)
     960            7 : ABI_SFREE(eps_model_m1_minus_one_DISTR)
     961            7 : ABI_SFREE(model_lanczos_vector_belongs_to_this_node)
     962            7 : ABI_SFREE(model_lanczos_vector_index)
     963              : 
     964            7 : end subroutine cleanup_projected_Sternheimer_epsilon
     965              : !!***
     966              : 
     967              : 
     968              : !!****f* m_hamiltonian/ProjectedSternheimerEpsilon
     969              : !! NAME
     970              : !!  ProjectedSternheimerEpsilon
     971              : !!
     972              : !! FUNCTION
     973              : !!  .
     974              : !!
     975              : !! INPUTS
     976              : !!
     977              : !! OUTPUT
     978              : !!
     979              : !! SOURCE
     980              : 
     981            7 : subroutine ProjectedSternheimerEpsilon(lmax, npt_gauss, second_model_parameter, &
     982            7 : list_projection_frequencies,nfrequencies,&
     983            7 : epsilon_eigenvalues_0,debug,use_model)
     984              : !----------------------------------------------------------------------------------------------------
     985              : ! This subroutine combines in a single subprogram the jobs of previous routines
     986              : !
     987              : !               - setup_projected_Sternheimer_epsilon
     988              : !               - compute_projected_Sternheimer_epsilon
     989              : !
     990              : ! The purpose of this combination is to avoid independent loops on nbandv, requiring the
     991              : ! arrays
     992              : !               projected_epsilon_M_matrix
     993              : !               projected_epsilon_B_matrix
     994              : !               projected_epsilon_G_matrix
     995              : !
     996              : ! from scaling like N^3, which grows very large with problem size.
     997              : !
     998              : ! Thus, this routine:
     999              : !
    1000              : !       -  Computes the frequency-dependent dielectric matrix in the Lanczos basis, using
    1001              : !          the projected Sternheimer equations.
    1002              : !
    1003              : !       -  Computes the frequency-dependent MODEL dielectric matrix in the complementary Lanczos basis.
    1004              : !
    1005              : !
    1006              : ! This routine will be verbose and write log files; indeed, large jobs crash in here, it will
    1007              : ! be important to know where/why!
    1008              : !
    1009              : ! The subroutine also computes the matrix elements on epsilon_model(iw) in the Lanczos basis;
    1010              : ! this is done here to avoid preforming direct products with the valence states again later.
    1011              : !----------------------------------------------------------------------------------------------------
    1012              : real(dp), parameter     :: svd_tolerance = 1.0e-16_dp
    1013              : 
    1014              : integer,     intent(in) :: lmax, npt_gauss
    1015              : integer,     intent(in) :: nfrequencies
    1016              : real(dp),    intent(in) :: list_projection_frequencies(nfrequencies)
    1017              : logical,     intent(in) :: debug
    1018              : real(dp),    intent(in) :: epsilon_eigenvalues_0(lmax)
    1019              : 
    1020              : logical,optional,intent(in) :: use_model
    1021              : 
    1022              : real(dp),    intent(in) :: second_model_parameter
    1023              : 
    1024              : 
    1025              : integer :: l, l1, l2
    1026              : integer :: i, iw, v
    1027              : integer :: recy_i
    1028              : integer :: lsolutions_max, lsolutions, ls
    1029              : integer :: projection
    1030              : 
    1031            7 : complex(dp), allocatable :: sternheimer_A0(:,:)
    1032            7 : complex(dp), allocatable :: sternheimer_A(:,:)
    1033            7 : complex(dp), allocatable :: sternheimer_B(:,:)
    1034            7 : complex(dp), allocatable :: sternheimer_X(:,:)
    1035            7 : complex(dp), allocatable :: sternheimer_G(:,:)
    1036              : 
    1037              : 
    1038            7 : complex(dp), allocatable :: dummy_tmp_1(:,:)
    1039            7 : complex(dp), allocatable :: dummy_tmp_2(:,:)
    1040              : 
    1041            7 : integer, allocatable      :: ipiv(:)
    1042              : 
    1043              : 
    1044              : 
    1045            7 : complex(dp),allocatable :: local_Lbasis(:,:)
    1046            7 : complex(dp),allocatable :: local_Lbasis_conjugated(:,:)
    1047            7 : complex(dp),allocatable :: YL(:)
    1048              : 
    1049            7 : real(dp), allocatable :: psikg_in(:,:), psikg_out(:,:)
    1050              : 
    1051            7 : real(dp), allocatable :: psik_wrk(:,:), psikg_wrk(:,:), psikb_wrk(:,:)
    1052            7 : real(dp), allocatable :: psi_gamma_l1(:,:), psi_gamma_l2(:,:)
    1053              : 
    1054            7 : real(dp), allocatable :: psikg_valence(:,:)
    1055            7 : real(dp), allocatable :: psir_valence(:,:,:,:)
    1056              : 
    1057            7 : real(dp), allocatable :: psi_rhs(:,:,:)
    1058              : 
    1059            7 : real(dp), allocatable :: psikg_VL(:,:)
    1060              : 
    1061              : 
    1062            7 : complex(dp), allocatable :: check_matrix(:,:), check_matrix2(:,:)
    1063            7 : complex(dp), allocatable :: c_sternheimer_solutions(:,:)
    1064            7 : complex(dp), allocatable :: QR_orthonormal_basis(:,:)
    1065              : 
    1066            7 : complex(dp), allocatable :: svd_matrix(:,:)
    1067            7 : real   (dp ), allocatable :: svd_values(:)
    1068              : 
    1069              : 
    1070              : integer                   :: iblk_lanczos, nbdblock_lanczos
    1071              : integer                   :: iblk_solutions, nbdblock_solutions
    1072              : integer                   :: mb
    1073              : 
    1074              : character(128) :: filename
    1075              : logical        :: file_exists
    1076              : integer        :: io_unit
    1077              : 
    1078              : character(128) :: filename_log
    1079              : integer        :: io_unit_log
    1080              : 
    1081              : 
    1082              : real(dp)      :: omega
    1083              : 
    1084              : character(256) :: timing_string
    1085              : real(dp)       :: time1, time2
    1086              : real(dp)       :: time_exact
    1087              : 
    1088              : 
    1089              : integer  :: info
    1090              : integer  :: ierr
    1091              : 
    1092              : real(dp)  ::  z(2)
    1093              : 
    1094              : 
    1095              : logical        :: omega_is_imaginary
    1096              : real(dp)       :: omega0
    1097              : 
    1098              : logical        :: model
    1099              : logical        :: write_debug
    1100              : 
    1101              : 
    1102              : integer        :: mpi_communicator, mpi_rank, mpi_group
    1103              : 
    1104              : ! *************************************************************************
    1105              : 
    1106              : 
    1107              : !================================================================================
    1108              : ! Prepare MPI information
    1109              : !================================================================================
    1110              : 
    1111              : ! for LA configuration ,The processors communicate over band+FFT
    1112            7 : mpi_communicator = mpi_enreg%comm_bandfft
    1113              : 
    1114              : ! what is the rank of this processor, within its group?
    1115            7 : mpi_rank  = mpi_enreg%me_fft
    1116              : 
    1117              : ! Which group does this processor belong to, given the communicator?
    1118            7 : mpi_group = mpi_enreg%me_band
    1119              : 
    1120              : 
    1121              : 
    1122              : 
    1123              : !================================================================================
    1124              : ! Setup a log file, to keep track of the algorithm
    1125              : !================================================================================
    1126              : 
    1127              : 
    1128            7 : write(filename_log,'(A,I4.4,A)') 'ProjectedSternheimerEpsilon_PROC=',mpi_enreg%me,'.log'
    1129              : 
    1130            7 : io_unit_log = get_unit()
    1131            7 : open(io_unit_log,file=filename_log,status=files_status_new)
    1132            7 : write(io_unit_log,10) ''
    1133            7 : write(io_unit_log,10) '#===================================================================================================='
    1134            7 : write(io_unit_log,10) "#                     ProjectedSternheimerEpsilon: log file                                          "
    1135            7 : write(io_unit_log,10) "#                     -------------------------------------------------------------------            "
    1136            7 : write(io_unit_log,10) "#                                                                                                    "
    1137            7 : write(io_unit_log,10) "# This file tracks the algorithm in the routine ProjectedSternheimerEpsilon. The goal is to          "
    1138            7 : write(io_unit_log,10) "# establish where the algorithm crashes if it does, and/or  to track are far along the code is.      "
    1139            7 : write(io_unit_log,10) '#'
    1140            7 : write(io_unit_log,10) '#  MPI data for this process:'
    1141            7 : write(io_unit_log,10) '#'
    1142            7 : write(io_unit_log,22) '#    mpi_rank :',mpi_rank,'  (rank of this processor in its band group)'
    1143            7 : write(io_unit_log,22) '#    mpi_group:',mpi_group,' (band group to which this processor belongs)'
    1144            7 : write(io_unit_log,10) '#===================================================================================================='
    1145            7 : flush(io_unit_log)
    1146              : 
    1147              : 
    1148              : !================================================================================
    1149              : ! Setup timing; prepare arrays
    1150              : !================================================================================
    1151              : 
    1152            7 : write(io_unit_log,10) " - Preparing and allocating arrays ...."
    1153            7 : flush(io_unit_log)
    1154              : 
    1155              : 
    1156              : 
    1157            7 : timing_string = "#"
    1158            7 : call write_text_block_in_Timing_log(timing_string)
    1159            7 : timing_string = "#        ProjectedSternheimerEpsilon "
    1160            7 : call write_text_block_in_Timing_log(timing_string)
    1161            7 : timing_string = "#"
    1162            7 : call write_text_block_in_Timing_log(timing_string)
    1163              : 
    1164              : ! Allocate the module array
    1165           35 : ABI_MALLOC(projected_dielectric_Lanczos_basis, (lmax,lmax,npt_gauss+1))
    1166              : 
    1167         5628 : projected_dielectric_Lanczos_basis(:,:,:) = cmplx_0
    1168              : 
    1169              : ! initialize zero frequency with exact solution
    1170           63 : do l = 1, lmax
    1171           63 : projected_dielectric_Lanczos_basis(l,l,1) = cmplx_1*epsilon_eigenvalues_0(l)
    1172              : end do
    1173              : 
    1174              : 
    1175              : ! initialize other frequencies with the identity
    1176           77 : do iw = 2, npt_gauss + 1
    1177          637 : do l = 1, lmax
    1178          630 : projected_dielectric_Lanczos_basis(l,l,iw) = cmplx_1
    1179              : end do
    1180              : end do
    1181              : 
    1182            7 : time_exact = zero
    1183              : 
    1184              : 
    1185              : !================================================================================
    1186              : ! Parallelisation of the code is subtle; Hamiltonian must act over
    1187              : ! FFT rows, we must be careful with memory, etc...
    1188              : !
    1189              : ! We will parallelise in block of Lanczos vectors, not over bands.
    1190              : !================================================================================
    1191              : 
    1192              : ! Number of blocks of lanczos vectors
    1193            7 : nbdblock_lanczos = lmax/blocksize
    1194            7 : if (modulo(lmax,blocksize) /= 0) nbdblock_lanczos = nbdblock_lanczos + 1
    1195              : 
    1196              : 
    1197            7 : if (present(use_model)) then
    1198            7 :   model = use_model
    1199              : else
    1200              :   model = .true.
    1201              : end if
    1202              : 
    1203            7 : if (model) then
    1204              :   ! Prepare the array that will contain the matrix elements of the model operator
    1205           24 :   ABI_MALLOC(model_dielectric_Lanczos_basis, (lmax,lmax,npt_gauss+1))
    1206              : 
    1207              :   ! initialize with zero. NOT with the identity, in order to avoid extra communications
    1208              :   ! (see below)
    1209         4824 :   model_dielectric_Lanczos_basis(:,:,:) = cmplx_0
    1210              : 
    1211              : end if
    1212              : 
    1213              : ! various working arrays
    1214              : 
    1215           21 : ABI_MALLOC(psikg_valence    ,(2,npw_g))
    1216           35 : ABI_MALLOC(psir_valence     ,(2,n4,n5,n6))
    1217              : 
    1218              : 
    1219           14 : ABI_MALLOC(psikg_VL ,(2,npw_g))
    1220              : 
    1221              : 
    1222           21 : ABI_MALLOC(psik_wrk         ,(2,npw_k))
    1223           21 : ABI_MALLOC(psikb_wrk        ,(2,npw_kb))
    1224           14 : ABI_MALLOC(psikg_wrk        ,(2,npw_g))
    1225              : 
    1226              : 
    1227           14 : ABI_MALLOC(psi_gamma_l1     ,(2,npw_k))
    1228           14 : ABI_MALLOC(psi_gamma_l2     ,(2,npw_k))
    1229              : 
    1230           28 : ABI_MALLOC(psi_rhs          ,(2,npw_k,lmax))
    1231              : 
    1232              : 
    1233           14 : ABI_MALLOC(psikg_in   ,(2,npw_g))
    1234           14 : ABI_MALLOC(psikg_out  ,(2,npw_g))
    1235              : 
    1236              : 
    1237              : ! maximal possible dimension of the solution space
    1238              : ! +1 because the solutions at $\omega=\infty$ are free.
    1239              : ! +1 if recycling is activated, because the solutions at $\omega=0$ are then available.
    1240            7 : i=1
    1241            7 : if(dtset%gwls_recycle == 1 .or. dtset%gwls_recycle == 2) then
    1242            7 :   i=2
    1243              : end if
    1244            7 : lsolutions_max = lmax*(nfrequencies+i)
    1245              : 
    1246              : 
    1247           28 : ABI_MALLOC(local_Lbasis,           (npw_k,lmax))
    1248           21 : ABI_MALLOC(local_Lbasis_conjugated,(npw_k,lmax))
    1249           21 : ABI_MALLOC(YL,(npw_k))
    1250              : 
    1251           28 : ABI_MALLOC(c_sternheimer_solutions,(npw_k,lsolutions_max))
    1252           21 : ABI_MALLOC(QR_orthonormal_basis   ,(npw_k,lsolutions_max))
    1253              : 
    1254              : 
    1255            7 : omega_is_imaginary = .true.
    1256              : 
    1257              : 
    1258           21 : ABI_MALLOC(svd_matrix,(npw_k,lsolutions_max))
    1259           21 : ABI_MALLOC(svd_values,(lsolutions_max))
    1260              : 
    1261              : 
    1262              : ! Prepare files for writing
    1263            7 : write_debug = debug .and. mpi_enreg%me == 0
    1264              : 
    1265              : if ( write_debug ) then
    1266              : 
    1267            0 :   write(filename,'(A)') "ProjectedSternheimerEpsilon.log"
    1268            0 :   inquire(file=filename,exist=file_exists)
    1269              : 
    1270            0 :   i = 0
    1271            0 :   do while (file_exists)
    1272            0 :   i = i+1
    1273            0 :   write (filename,'(A,I0.4,A)') "ProjectedSternheimerEpsilon_",i,".log"
    1274            0 :   inquire(file=filename,exist=file_exists)
    1275              :   end do
    1276              : 
    1277              : 
    1278            0 :   io_unit = get_unit()
    1279            0 :   open(io_unit,file=filename,status=files_status_new)
    1280            0 :   write(io_unit,10) ''
    1281            0 :   write(io_unit,10) '#===================================================================================================='
    1282            0 :   write(io_unit,10) "#                     Building the dielectic matrix using projected Sternheimer equation             "
    1283            0 :   write(io_unit,10) "#                     -------------------------------------------------------------------            "
    1284            0 :   write(io_unit,10) "#                                                                                                    "
    1285            0 :   write(io_unit,10) '# This file contains some tests to check if the various elements entering the projected  '
    1286            0 :   write(io_unit,10) '# dielectric matrix have the right properties. At this point, this is mostly for debugging.'
    1287            0 :   write(io_unit,10) '# The wavefunctions and other related arrays are stored in reciprocal space.'
    1288            0 :   write(io_unit,10) '#'
    1289            0 :   write(io_unit,10) '#===================================================================================================='
    1290            0 :   write(io_unit,10) ''
    1291            0 :   flush(io_unit)
    1292              : end if
    1293              : 
    1294            7 : if (debug) then
    1295            0 :   ABI_MALLOC(check_matrix ,(lsolutions_max,lsolutions_max))
    1296            0 :   ABI_MALLOC(check_matrix2,(lsolutions_max,lsolutions_max))
    1297              : end if
    1298              : 
    1299              : !================================================================================
    1300              : !  Loop on all valence bands
    1301              : !================================================================================
    1302              : 
    1303              : 
    1304              : 
    1305              : 
    1306           35 : do v = 1, nbandv
    1307           28 : write(io_unit_log,10) '#===================================================================================================='
    1308           28 : write(io_unit_log,20) '#  valence band index:', v
    1309           28 : write(io_unit_log,10) '#===================================================================================================='
    1310           28 : flush(io_unit_log)
    1311              : 
    1312              : 
    1313              : 
    1314              : 
    1315           28 : if ( write_debug ) then
    1316            0 :   write(io_unit,10) '#===================================================================================================='
    1317            0 :   write(io_unit,20) '#  valence band index:', v
    1318            0 :   write(io_unit,10) '#===================================================================================================='
    1319            0 :   flush(io_unit)
    1320              : end if
    1321              : 
    1322           28 : write(io_unit_log,10) '   - Fourier transform valence state ...'
    1323           28 : flush(io_unit_log)
    1324              : 
    1325              : 
    1326              : ! copy pre-calculated valence state in this covenient local array
    1327        15448 : psikg_valence(:,:) = kernel_wavefunctions_FFT(:,:,v)
    1328              : 
    1329              : ! compute fourier transform of valence state, and conjugate
    1330           28 : call g_to_r(psir_valence,psikg_valence)
    1331       192052 : psir_valence(2,:,:,:) = -psir_valence(2,:,:,:)
    1332              : 
    1333              : ! loop on all blocks of lanczos vectors
    1334           28 : write(io_unit_log,10) '   - Loop on all lanczos blocks to generate modified basis and Sternheimer RHS:'
    1335           28 : flush(io_unit_log)
    1336          188 : do iblk_lanczos = 1, nbdblock_lanczos
    1337              : !--------------------------------------------------------------------------
    1338              : ! Below, we build the modified basis, [ (V^{1/2} l)^* . psi_v],
    1339              : ! as well as conjugated, projected form, Pc . [ (V^{1/2} l) . psi_v^*].
    1340              : !
    1341              : ! It is very irritating to have to do it this way, but I don't
    1342              : ! see an alternative; see discussion below.
    1343              : !
    1344              : !--------------------------------------------------------------------------
    1345              : 
    1346          160 : write(io_unit_log,23) '       iblk_lanczos  = ',iblk_lanczos," / ",nbdblock_lanczos
    1347              : 
    1348              : 
    1349          160 : write(io_unit_log,10) '          -- Prepare modified basis computation...'
    1350          160 : flush(io_unit_log)
    1351              : 
    1352              : 
    1353              : 
    1354              : ! loop on all states within this block
    1355          384 : do mb = 1, blocksize
    1356              : 
    1357              : ! Determine the index of the Lanczos vector
    1358          224 : l = (iblk_lanczos-1)*blocksize + mb
    1359              : 
    1360              : ! take a single lanczos vector
    1361              : 
    1362          224 : if ( l <= lmax) then
    1363        33120 :   psik_wrk(1,:) = dble (Lbasis_lanczos(:,l))
    1364        33120 :   psik_wrk(2,:) = dimag(Lbasis_lanczos(:,l))
    1365              : else
    1366            0 :   psik_wrk(:,:) =  zero
    1367              : end if
    1368              : 
    1369              : 
    1370              : ! Apply coulomb potential
    1371          224 : call sqrt_vc_k(psik_wrk)
    1372              : 
    1373              : ! Store in array of blocks of wavefunctions
    1374        99072 : psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k) = psik_wrk(:,:)
    1375              : 
    1376              : end do ! mb
    1377              : 
    1378              : ! Transform to FFT representation
    1379          160 : call wf_block_distribute(psikb_wrk,  psikg_VL,1) ! LA -> FFT
    1380              : 
    1381              : ! psikg_VL now contains | V^1/2 . l >, in FFT configuration
    1382              : 
    1383              : 
    1384              : !----------------------------------------------------------
    1385              : ! i) Compute the modified basis
    1386              : !----------------------------------------------------------
    1387          160 : write(io_unit_log,10) '          -- compute modified basis ...'
    1388          160 : flush(io_unit_log)
    1389              : 
    1390              : 
    1391              : 
    1392              : ! Fourier transform to real space, and conjugate (psir1 is a global work array)
    1393          160 : call g_to_r(psir1,psikg_VL)
    1394      1097440 : psir1(2,:,:,:) = -psir1(2,:,:,:) ! IS THIS STACK-DANGEROUS?
    1395              : 
    1396              : ! Compute the real space product, and return to k space, in FFT configuration
    1397          160 : call gr_to_g(psikg_wrk,psir1,psikg_valence)
    1398              : 
    1399              : ! psikg_wrk contains | (V^1/2 . l)^* phi_v >, in FFT configuration
    1400              : 
    1401              : ! return to LA representation
    1402          160 : call wf_block_distribute(psikb_wrk,  psikg_wrk,2) ! FFT -> LA
    1403              : 
    1404              : ! store data, in LA representation
    1405          384 : do mb = 1, blocksize
    1406          224 : l = (iblk_lanczos-1)*blocksize + mb
    1407              : 
    1408          384 : if ( l <= lmax) then
    1409              :   ! local_Lbasis
    1410        98912 :   psik_wrk(:,:)     = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
    1411        33120 :   local_Lbasis(:,l) = cmplx_1*psik_wrk(1,:)+cmplx_i*psik_wrk(2,:)
    1412              : end if
    1413              : 
    1414              : end do !mb
    1415              : 
    1416              : !--------------------------------------------------------------------------
    1417              : ! ii) Build the Sternheimer coefficients, at various frequencies,
    1418              : !     to define the Sternheimer basis.
    1419              : !--------------------------------------------------------------------------
    1420          160 : write(io_unit_log,20) '          -- Compute Sternheimer RHS...'
    1421          160 : flush(io_unit_log)
    1422              : 
    1423              : 
    1424              : ! psikg_wrk still contains | (V^1/2 . l)^* phi_v >, in FFT configuration
    1425              : 
    1426              : !  Create right-hand-side of Sternheimer equation, in FFT configuration
    1427          160 : call pc_k_valence_kernel(psikg_wrk)
    1428          160 : call Hpsik(psikg_in,psikg_wrk,eig(v))
    1429          160 : call pc_k_valence_kernel(psikg_in)
    1430        98848 : psikg_in(:,:) = -psikg_in(:,:) ! IS THIS STACK-DANGEROUS?
    1431              : 
    1432              : ! return RHS  to LA representation, for explicit storage
    1433          160 : call wf_block_distribute(psikb_wrk,  psikg_in,2) ! FFT -> LA
    1434              : 
    1435              : ! store data, in LA representation
    1436          384 : do mb = 1, blocksize
    1437          224 : l = (iblk_lanczos-1)*blocksize + mb
    1438              : 
    1439          384 : if ( l <= lmax) then
    1440              :   ! psi_rhs
    1441        98912 :   psi_rhs(:,:,l)    = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
    1442              : end if
    1443              : 
    1444              : end do !mb
    1445              : 
    1446              : !----------------------------------------------------------
    1447              : ! iii) extract solutions for all projection frequencies
    1448              : !----------------------------------------------------------
    1449          160 : write(io_unit_log,20) '          -- Extract solutions for all projection frequencies...'
    1450          160 : flush(io_unit_log)
    1451              : 
    1452              : 
    1453              : 
    1454          160 : do iw = 1, nfrequencies
    1455              : 
    1456            0 : omega0 = list_projection_frequencies(iw)
    1457              : ! Solve Sternheimer equation
    1458              : 
    1459            0 : projection = 0
    1460            0 : if(omega0 < 1d-12) projection=1
    1461              : 
    1462              : ! solve A x = b, over the whole lanczos block
    1463            0 : call sqmr(psikg_in, psikg_out, eig(v), projection, omega0, omega_is_imaginary)
    1464              : 
    1465              : ! return LA representation, for explicit storage
    1466            0 : call wf_block_distribute(psikb_wrk,  psikg_out, 2) ! FFT -> LA
    1467              : 
    1468          160 : do mb = 1, blocksize
    1469            0 : l = (iblk_lanczos-1)*blocksize + mb
    1470              : 
    1471            0 : if ( l <= lmax) then
    1472            0 :   ls = (l-1)*nfrequencies+iw
    1473              : 
    1474            0 :   psik_wrk(:,:)     = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
    1475              : 
    1476            0 :   c_sternheimer_solutions(:,ls)= cmplx_1*psik_wrk(1,:)+cmplx_i*psik_wrk(2,:)
    1477              : end if
    1478              : 
    1479              : end do ! mb
    1480              : 
    1481              : end do ! iw
    1482              : 
    1483              : !----------------------------------------------------------
    1484              : ! iv) Compute the conjugated, projected modified basis
    1485              : !----------------------------------------------------------
    1486              : 
    1487          160 : write(io_unit_log,20) '          -- compute the conjugated, projected modified basis...'
    1488          160 : flush(io_unit_log)
    1489              : 
    1490              : 
    1491              : 
    1492              : 
    1493              : ! Compute the real space product, | (V^1/2. l) phi_v^* > and return to k space, in FFT configuration
    1494          160 : call gr_to_g(psikg_wrk, psir_valence, psikg_VL)
    1495              : 
    1496              : ! project on conduction states
    1497          160 : call pc_k_valence_kernel(psikg_wrk)
    1498              : 
    1499              : ! return to LA representation
    1500          160 : call wf_block_distribute(psikb_wrk,  psikg_wrk,2) ! FFT -> LA
    1501              : 
    1502              : ! store back, in LA configuration
    1503          412 : do mb = 1, blocksize
    1504          224 : l = (iblk_lanczos-1)*blocksize + mb
    1505              : 
    1506          384 : if ( l <= lmax) then
    1507        98912 :   psik_wrk(:,:) = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
    1508        33120 :   local_Lbasis_conjugated(:,l) = cmplx_1*psik_wrk(1,:)+cmplx_i*psik_wrk(2,:)
    1509              : end if
    1510              : 
    1511              : end do !mb
    1512              : 
    1513              : end do ! iblk_lanczos
    1514              : 
    1515              : 
    1516              : 
    1517           28 : write(io_unit_log,10) '   - Read in solutions at w=0 and/or w = infinity, if appropriate...'
    1518           28 : flush(io_unit_log)
    1519              : 
    1520              : ! Begin with the storage of the solutions at $\omega = 0.$, which are free.
    1521           28 : if(dtset%gwls_recycle == 1) then
    1522              :   c_sternheimer_solutions(:,lsolutions_max-2*lmax+1:lsolutions_max-lmax) = cmplx_1*Sternheimer_solutions_zero(1,:,:,v) + &
    1523         8368 :   &                                                                             cmplx_i*Sternheimer_solutions_zero(2,:,:,v)
    1524              : end if
    1525           28 : if(dtset%gwls_recycle == 2) then
    1526          108 :   do i=1,lmax
    1527           96 :   recy_i = (i-1)*nbandv + v
    1528              :   !BUG : On petrus, NAG 5.3.1 + OpenMPI 1.6.2 cause read(...,rec=i) to read the data written by write(...,rec=i+1).
    1529           96 :   read(recy_unit,rec=recy_i) psik_wrk
    1530        24780 :   c_sternheimer_solutions(:,lsolutions_max-2*lmax+i) = cmplx_1*psik_wrk(1,:) + cmplx_i*psik_wrk(2,:)
    1531              :   end do
    1532              : end if
    1533              : 
    1534              : ! and then continue with the storage of the vectors on which the Sternheimer solutions will be projected.
    1535        33148 : c_sternheimer_solutions(:,lsolutions_max-lmax+1:lsolutions_max) = cmplx_1*psi_rhs(1,:,:) + cmplx_i*psi_rhs(2,:,:)
    1536              : ! Previously was = local_Lbasis; but analysis in the Lanczos article reveals psi_rhs should be better.
    1537              : ! Furthermore, tests show that, with psi_rhs, silane@1Ha has Sigma_c 0.01mHa away from the result with
    1538              : ! gwls_list_proj_freq 0.0 1.0, in contrast with local_Lbasis, which has Sigma_c 0.3mHa away from the same result.
    1539              : 
    1540           28 : if ( model ) then
    1541              : 
    1542           24 :   write(io_unit_log,10) '   - USE MODEL: model = .true., hence compute model model dielectric matrix...'
    1543           24 :   flush(io_unit_log)
    1544              : 
    1545              : 
    1546              : 
    1547              :   !--------------------------------------------------------------------------
    1548              :   ! Now that we have the modified basis, compute the matrix
    1549              :   ! elements of the model dielectric operator
    1550              :   !
    1551              :   ! CAREFUL!
    1552              :   !
    1553              :   !        The model is given by
    1554              :   !
    1555              :   !                P_model(iw) = sum_{v} phi_v(r) P_c.Y(iw).P_c phi_v^*(r')
    1556              :   !
    1557              :   !    such that
    1558              :   !
    1559              :   !    <l1 | eps_model(iw) | l2 >  = delta_{l1,l2}
    1560              :   !    - sum_{v} < (V^{1/2}.l1).phi_v^*| Pc . Y . Pc | (V^{1/2}.l2).phi_v^* >
    1561              :   !
    1562              :   ! But local_Lbasis defined above corresponds to
    1563              :   !                                Pc | (V^{1/2} .l )^* phi_v >.
    1564              :   !
    1565              :   ! This is why we must define local_Lbasis_conjugated, of the form
    1566              :   !                                Pc | (V^{1/2} .l ) phi_v^* >.
    1567              :   !
    1568              :   !--------------------------------------------------------------------------
    1569              : 
    1570          288 :   do iw = 1, npt_gauss+1
    1571              : 
    1572          264 :   call setup_Pk_model(list_omega(iw),second_model_parameter)
    1573              : 
    1574              :   ! Only build the lower triangular part; the upper triangular part is obtained from the Hermitian conjugate
    1575         2400 :   do l1 = 1, lmax
    1576              : 
    1577       273504 :   YL(:) = model_Y_LA(:)*local_Lbasis_conjugated(:,l1)
    1578        11880 :   do l2 = 1, l1
    1579              :   model_dielectric_Lanczos_basis(l1,l2,iw) = model_dielectric_Lanczos_basis(l1,l2,iw)  &
    1580        11616 :   -complex_vector_product(YL, local_Lbasis_conjugated(:,l2),npw_k)
    1581              : 
    1582              :   end do
    1583              :   end do
    1584              : 
    1585              :   end do ! iw
    1586              : 
    1587              : 
    1588              : end if
    1589              : 
    1590              : 
    1591              : !--------------------------------------------------------------------------
    1592              : ! Check explicitly that solutions satisfy the Sternheimer equations
    1593              : !--------------------------------------------------------------------------
    1594              : 
    1595           28 : if ( debug ) then
    1596              : 
    1597            0 :   if (write_debug) then
    1598            0 :     write(io_unit,10) "#--------------------------------------------------------------------------------"
    1599            0 :     write(io_unit,10) "# Check explicitly that solutions satisfy the Sternheimer equation.              "
    1600            0 :     write(io_unit,10) "#                                                                                "
    1601            0 :     write(io_unit,10) "# Define:                                                                        "
    1602            0 :     write(io_unit,10) "# E_l = || (omega^2+[H-Ev]^2) |phi_l> + Pc.[H-Ev].Pc |(V^1/2.q_l)^*.phi_v >  ||  "
    1603            0 :     write(io_unit,10) "#--------------------------------------------------------------------------------"
    1604            0 :     write(io_unit,10) '#  l                Im[omega] (Ha)                  E_l'
    1605            0 :     write(io_unit,10) "#--------------------------------------------------------------------------------"
    1606            0 :     flush(io_unit)
    1607              :   end if
    1608              : 
    1609              : 
    1610            0 :   do iblk_lanczos = 1, nbdblock_lanczos
    1611              : 
    1612              :   ! loop on all states within this block
    1613            0 :   do mb = 1, blocksize
    1614              : 
    1615            0 :   l = (iblk_lanczos-1)*blocksize + mb
    1616              : 
    1617              : 
    1618            0 :   if ( l <= lmax) then
    1619              :     ! psik_wrk = | (V^{1/2} .l )^* phi_v >
    1620            0 :     psik_wrk(1,:) = dble (local_Lbasis(:,l))
    1621            0 :     psik_wrk(2,:) = dimag(local_Lbasis(:,l))
    1622              :   else
    1623            0 :     psik_wrk(:,:) = zero
    1624              :   end if
    1625              : 
    1626              :   ! Store in array of blocks of wavefunctions
    1627            0 :   psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k) = psik_wrk(:,:)
    1628              :   end do ! mb
    1629              : 
    1630              :   ! Transform to FFT representation
    1631            0 :   call wf_block_distribute(psikb_wrk,  psikg_wrk, 1) ! LA -> FFT
    1632              : 
    1633              :   !  Create right-hand-side of Sternheimer equation
    1634            0 :   call pc_k_valence_kernel(psikg_wrk)
    1635            0 :   call Hpsik(psikg_in,psikg_wrk,eig(v))
    1636            0 :   call pc_k_valence_kernel(psikg_in)
    1637            0 :   psikg_in(:,:)  = -psikg_in(:,:) ! IS THIS STACK-DANGEROUS?
    1638              : 
    1639            0 :   do iw = 1, nfrequencies
    1640              :   ! loop on all states within this block
    1641            0 :   do mb = 1, blocksize
    1642              : 
    1643            0 :   l = (iblk_lanczos-1)*blocksize + mb
    1644              : 
    1645            0 :   ls = (l-1)*nfrequencies+iw
    1646              : 
    1647            0 :   if ( l <= lmax) then
    1648            0 :     psik_wrk(1,:) = dble (c_sternheimer_solutions(:,ls))
    1649            0 :     psik_wrk(2,:) = dimag(c_sternheimer_solutions(:,ls))
    1650              :   else
    1651            0 :     psik_wrk(:,:) = zero
    1652              :   end if
    1653              : 
    1654              :   ! Store in array of blocks of wavefunctions
    1655            0 :   psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k) = psik_wrk(:,:)
    1656              :   end do
    1657              : 
    1658              :   ! Transform to FFT representation
    1659            0 :   call wf_block_distribute(psikb_wrk,  psikg_wrk, 1) ! LA -> FFT
    1660              : 
    1661              : 
    1662            0 :   omega0 = list_projection_frequencies(iw)
    1663              : 
    1664            0 :   psikg_out(:,:) = omega0**2*psikg_wrk(:,:)
    1665              : 
    1666            0 :   call Hpsik(psikg_wrk,cte=eig(v))
    1667            0 :   call Hpsik(psikg_wrk,cte=eig(v))
    1668              : 
    1669              : 
    1670            0 :   psikg_out(:,:) = psikg_out(:,:) + psikg_wrk(:,:)-psikg_in(:,:)
    1671              :   ! psikg_out now contains [ w0^2 + [H-epsilon_v]^2 ] | x > - |RHS>, in FFT configuration.
    1672              : 
    1673              :   ! bring it back to LA configuration
    1674              : 
    1675              :   ! Transform to FFT representation
    1676            0 :   call wf_block_distribute(psikb_wrk,  psikg_out, 2) ! FFT -> LA
    1677              : 
    1678            0 :   do mb = 1, blocksize
    1679            0 :   l = (iblk_lanczos-1)*blocksize + mb
    1680              : 
    1681            0 :   if ( l <= lmax) then
    1682            0 :     psik_wrk(:,:) = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
    1683              : 
    1684            0 :     z(:) = cg_zdotc(npw_k ,psik_wrk, psik_wrk)
    1685              : 
    1686            0 :     call xmpi_sum(z, mpi_communicator,ierr) ! sum on all processors working on FFT!
    1687            0 :     if (write_debug) write(io_unit,21)  l, omega0, sqrt(z(1))
    1688              :   end if
    1689              :   end do ! mb
    1690              : 
    1691              :   end do ! iw
    1692              :   end do ! iblk_lanczos
    1693              : 
    1694              : end if
    1695              : 
    1696              : !--------------------------------------------------------------------------
    1697              : ! Step 5: Perform a singular value decomposition to extract a
    1698              : !         linearly independent basis for the solution space.
    1699              : !
    1700              : !--------------------------------------------------------------------------
    1701           28 : write(io_unit_log,10) '   - Perform SVD to extract linearly independent basis to Sternheimer equation...'
    1702           28 : flush(io_unit_log)
    1703              : 
    1704              : 
    1705              : 
    1706              : 
    1707        66268 : svd_matrix(:,:) =  c_sternheimer_solutions(:,:)
    1708              : 
    1709           28 : call extract_SVD(mpi_communicator, npw_k,lsolutions_max,svd_matrix,svd_values)
    1710              : 
    1711           28 : if ( write_debug ) then
    1712            0 :   write(io_unit,10) "#--------------------------------------------------------------------------------"
    1713            0 :   write(io_unit,10) "# Check the singular value decomposition of the arrays"
    1714            0 :   write(io_unit,10) '#  l                          svd'
    1715            0 :   write(io_unit,10) "#--------------------------------------------------------------------------------"
    1716            0 :   flush(io_unit)
    1717              : end if
    1718              : 
    1719           28 : lsolutions = 0
    1720        66268 : QR_orthonormal_basis(:,:) = cmplx_0
    1721          476 : do l=1, lsolutions_max
    1722          476 : if (svd_values(l) > svd_tolerance ) then
    1723          448 :   lsolutions = lsolutions + 1
    1724              : 
    1725          448 :   if ( write_debug ) then
    1726            0 :     write(io_unit,14)   l,svd_values(l)
    1727            0 :     flush(io_unit)
    1728              :   end if
    1729        66240 :   QR_orthonormal_basis(:,l) = svd_matrix(:,l)
    1730              : 
    1731              : else
    1732            0 :   if ( write_debug ) then
    1733            0 :     write(io_unit,15)   l,svd_values(l),' SVD value too small! Vector to be discarded!'
    1734            0 :     flush(io_unit)
    1735              :   end if
    1736              : end if
    1737              : end do
    1738              : 
    1739              : !--------------------------------------------------------------------------
    1740              : ! Step 6: project all relevant arrays onto the newly defined orthonormal
    1741              : !         basis.
    1742              : !--------------------------------------------------------------------------
    1743           28 : write(io_unit_log,10) '   - Compute the B matrix...'
    1744           28 : flush(io_unit_log)
    1745              : 
    1746           28 : if (debug) then
    1747            0 :   check_matrix(:,:) = cmplx_0
    1748            0 :   do l = 1, lsolutions
    1749            0 :   check_matrix(l,l) = -cmplx_1
    1750              :   end do
    1751              : end if
    1752              : 
    1753           84 : ABI_MALLOC(ipiv                ,(lsolutions))
    1754          112 : ABI_MALLOC(sternheimer_A0      ,(lsolutions,lsolutions))
    1755          112 : ABI_MALLOC(sternheimer_B       ,(lsolutions,lmax))
    1756          112 : ABI_MALLOC(sternheimer_G       ,(lmax,lsolutions))
    1757              : 
    1758              : ! Compute the X matrix and the check_matrix
    1759          476 : do l1 = 1, lsolutions
    1760              : 
    1761        66240 : psi_gamma_l1(1,:) = real (QR_orthonormal_basis(:,l1))
    1762        66240 : psi_gamma_l1(2,:) = dimag(QR_orthonormal_basis(:,l1))
    1763              : 
    1764         7644 : do l2 = 1, lsolutions
    1765              : 
    1766         7168 : if (l2 <= lmax) then
    1767         3584 :   z(:) = cg_zdotc(npw_k, psi_gamma_l1,  psi_rhs(:,:,l2))
    1768         3584 :   call xmpi_sum(z, mpi_communicator,ierr) ! sum on all processors for LA configuration
    1769              : 
    1770         3584 :   sternheimer_B(l1,l2) = cmplx_1*z(1)+cmplx_i*z(2)
    1771              : end if
    1772              : 
    1773         7616 : if (debug)  then
    1774            0 :   psi_gamma_l2(1,:) = dble (QR_orthonormal_basis(:,l2))
    1775            0 :   psi_gamma_l2(2,:) = dimag(QR_orthonormal_basis(:,l2))
    1776              : 
    1777            0 :   z(:) = cg_zdotc(npw_k, psi_gamma_l1,  psi_gamma_l2)
    1778            0 :   call xmpi_sum(z, mpi_communicator,ierr) ! sum on all processors
    1779              : 
    1780            0 :   check_matrix(l1,l2) = check_matrix(l1,l2) + cmplx_1*z(1)+cmplx_i*z(2)
    1781              : end if
    1782              : 
    1783              : end do ! l2
    1784              : end do ! l1
    1785              : 
    1786              : 
    1787              : ! Number of blocks of solution vectors
    1788           28 : nbdblock_solutions = lsolutions/blocksize
    1789              : 
    1790           28 : if (modulo(lsolutions,blocksize) /= 0) nbdblock_solutions = nbdblock_solutions + 1
    1791              : 
    1792              : 
    1793           28 : write(io_unit_log,10) '   - Compute the A0 matrix...'
    1794           28 : flush(io_unit_log)
    1795              : 
    1796              : ! Compute the A matrix
    1797          348 : do iblk_solutions =1, nbdblock_solutions
    1798              : 
    1799          768 : do mb = 1, blocksize
    1800          448 : l2 = (iblk_solutions-1)*blocksize + mb
    1801              : 
    1802          448 : if ( l2 <= lsolutions) then
    1803        66240 :   psik_wrk(1,:) = dble (QR_orthonormal_basis(:,l2))
    1804        66240 :   psik_wrk(2,:) = dimag(QR_orthonormal_basis(:,l2))
    1805              : else
    1806            0 :   psik_wrk(:,:) =  zero
    1807              : end if
    1808              : 
    1809              : ! Store in array of blocks of wavefunctions
    1810       198144 : psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k) = psik_wrk(:,:)
    1811              : end do
    1812              : 
    1813              : ! Transform to FFT representation
    1814          320 : call wf_block_distribute(psikb_wrk,  psikg_wrk,1) ! LA -> FFT
    1815              : 
    1816              : ! act twice with the Hamiltonian operator
    1817          320 : call Hpsik(psikg_out,psikg_wrk,eig(v))
    1818          320 : call Hpsik(psikg_out,cte=eig(v))
    1819              : 
    1820              : ! return to LA representation
    1821          320 : call wf_block_distribute(psikb_wrk,  psikg_out,2) ! FFT -> LA
    1822              : 
    1823          796 : do mb = 1, blocksize
    1824          448 : l2 = (iblk_solutions-1)*blocksize + mb
    1825              : 
    1826          448 : if ( l2 <= lsolutions) then
    1827       197824 :   psik_wrk(:,:)     = psikb_wrk(:,(mb-1)*npw_k+1:mb*npw_k)
    1828              : else
    1829            0 :   psik_wrk(:,:)     = zero
    1830              : end if
    1831              : 
    1832         7936 : do l1 = 1, lsolutions
    1833              : 
    1834      1059840 : psi_gamma_l1(1,:) = real (QR_orthonormal_basis(:,l1))
    1835      1059840 : psi_gamma_l1(2,:) = dimag(QR_orthonormal_basis(:,l1))
    1836              : 
    1837         7168 : z(:) = cg_zdotc(npw_k, psi_gamma_l1,  psik_wrk)
    1838         7168 : call xmpi_sum(z,mpi_communicator,ierr) ! sum on all processors working on FFT!
    1839              : 
    1840              : 
    1841         7616 : if ( l2 <= lsolutions ) then
    1842         7168 :   sternheimer_A0(l1,l2) = cmplx_1*z(1)+cmplx_i*z(2)
    1843              : end if
    1844              : 
    1845              : 
    1846              : end do ! l1
    1847              : end do ! mb
    1848              : end do ! iblk_solutions
    1849              : 
    1850              : 
    1851           28 : if (debug) then
    1852              :   ! HERE we use a dummy variable to avoid operations which might blow the stack!
    1853              :   ! Stack overflows lead to hard-to-find bugs; let's avoid putting them in here.
    1854            0 :   ABI_MALLOC(dummy_tmp_1,(lsolutions,lsolutions))
    1855            0 :   ABI_MALLOC(dummy_tmp_2,(lsolutions,lsolutions))
    1856              : 
    1857              : 
    1858            0 :   dummy_tmp_1(:,:)= transpose(sternheimer_A0(:,:))
    1859            0 :   dummy_tmp_2(:,:)= conjg(dummy_tmp_1(:,:))
    1860              : 
    1861            0 :   check_matrix2(:,:) = sternheimer_A0(:,:)-dummy_tmp_2(:,:)
    1862              : 
    1863            0 :   ABI_FREE(dummy_tmp_1)
    1864            0 :   ABI_FREE(dummy_tmp_2)
    1865              : end if
    1866              : 
    1867           28 : write(io_unit_log,10) '   - Compute the GAMMA matrix...'
    1868           28 : flush(io_unit_log)
    1869              : 
    1870              : 
    1871              : ! Compute the GAMMA matrices
    1872          252 : do l1 = 1, lmax
    1873              : 
    1874              : ! psik_wrk = | (V^{1/2} . l )^* phi_v >
    1875        33120 : psik_wrk(1,:) = dble (local_Lbasis(:,l1) )
    1876        33120 : psik_wrk(2,:) = dimag(local_Lbasis(:,l1))
    1877              : 
    1878              : 
    1879         3836 : do l2 = 1, lsolutions
    1880              : 
    1881       529920 : psi_gamma_l2(1,:) = real (QR_orthonormal_basis(:,l2))
    1882       529920 : psi_gamma_l2(2,:) = dimag(QR_orthonormal_basis(:,l2))
    1883              : 
    1884              : 
    1885              : ! Note that G_{lJ} = < l | Vc^{1/2}.(gamma_J^*.phi_v)>
    1886              : !                  = < gamma_J | (Vc^{1/2}.l^*).phi_v >
    1887              : 
    1888         3584 : z(:) = cg_zdotc(npw_k,psi_gamma_l2, psik_wrk)
    1889         3584 : call xmpi_sum(z,mpi_communicator,ierr) ! sum on all processors working on FFT!
    1890         3808 : sternheimer_G(l1,l2) = cmplx_1*z(1)+cmplx_i*z(2)
    1891              : 
    1892              : end do ! l1
    1893              : end do ! l2
    1894              : 
    1895              : 
    1896              : 
    1897           28 : if ( write_debug ) then
    1898            0 :   write(io_unit,19)   '<gamma| gamma>', sqrt(sum(abs(check_matrix(:,:))**2))
    1899            0 :   write(io_unit,19)   '  M hermitian ',sqrt(sum(abs(check_matrix2(:,:))**2))
    1900            0 :   write(io_unit,10)   " "
    1901            0 :   write(io_unit,10)   "# GAMMA Matrix:"
    1902            0 :   write(io_unit,10)   " "
    1903              : 
    1904            0 :   do l1 = 1, lmax
    1905            0 :   write(io_unit,30) sternheimer_G(l1,:)
    1906              :   end do
    1907            0 :   flush(io_unit)
    1908              : end if
    1909              : 
    1910              : !--------------------------------------------------------------------------
    1911              : ! Step 7: Compute the solutions
    1912              : !--------------------------------------------------------------------------
    1913              : 
    1914           28 : write(io_unit_log,10) '   - Compute the Projected Sternheimer solutions and build approximate dielectric operator...'
    1915           28 : flush(io_unit_log)
    1916              : 
    1917              : 
    1918              : 
    1919           84 : ABI_MALLOC(sternheimer_A ,(lsolutions,lsolutions))
    1920           84 : ABI_MALLOC(sternheimer_X       ,(lsolutions,lmax))
    1921          308 : do iw = 2, npt_gauss + 1
    1922              : 
    1923          280 : write(io_unit_log,23) '        -- iw = ',iw,' / ',npt_gauss+1
    1924          280 : flush(io_unit_log)
    1925              : 
    1926              : 
    1927          280 : omega = list_omega(iw)
    1928              : 
    1929        76440 : sternheimer_A(:,:) = sternheimer_A0(:,:)
    1930              : 
    1931         4760 : do l = 1, lsolutions
    1932         4760 : sternheimer_A(l,l) = sternheimer_A(l,l) + omega**2
    1933              : end do
    1934              : 
    1935        38360 : sternheimer_X(:,:) = sternheimer_B(:,:)
    1936              : 
    1937              : !--------------------------------------------------------------------------
    1938              : ! Step 2:  solve A*X = B, a projected form of the Sternheimer equation
    1939              : !--------------------------------------------------------------------------
    1940          280 : write(io_unit_log,10) '        -- Solve A*X = B'
    1941          280 : flush(io_unit_log)
    1942              : 
    1943              : 
    1944              : 
    1945          280 : call cpu_time(time1)
    1946              : call zgesv(lsolutions,      & ! number of rows of A matrix
    1947              : lmax,            & ! number of columns of B matrix
    1948              : sternheimer_A,   & ! The A matrix on input, the LU factorization on output
    1949              : lsolutions,      & ! leading dimension of A
    1950              : ipiv,            & ! array of pivots
    1951              : sternheimer_X,   & ! B matrix on input, solution X on output
    1952              : lsolutions,      & ! leading dimension of B
    1953          280 : info )
    1954          280 : call cpu_time(time2)
    1955              : 
    1956          280 : time_exact = time_exact + time2-time1
    1957              : 
    1958              : !--------------------------------------------------------------------------
    1959              : ! Step 3: Add contribution to projected epsilon
    1960              : !--------------------------------------------------------------------------
    1961              : ! perform E = E  -4 sum_l Gamma_v*X^*_v
    1962              : 
    1963          280 : write(io_unit_log,10) '        -- add contribution to dielectric matrix at this frequency'
    1964          280 : flush(io_unit_log)
    1965              : 
    1966              : 
    1967              : 
    1968         1120 : ABI_MALLOC(dummy_tmp_1,(lsolutions,lmax))
    1969        38360 : dummy_tmp_1(:,:) = conjg(sternheimer_X) ! DO THIS to avoid potential stack problems
    1970              : 
    1971          280 : call cpu_time(time1)
    1972              : call zgemm(     'N',    & ! A matrix is in normal order
    1973              : 'N',    & ! B matrix is in normal order
    1974              : lmax,    & ! number of rows of A
    1975              : lmax,    & ! number of columns of B
    1976              : lsolutions,    & ! number of columns of A
    1977              : -4.0_dp*cmplx_1,    & ! premultiply A*B by this scalar
    1978              : sternheimer_G,    & ! GAMMA matrix
    1979              : lmax,    & ! leading dimension of A
    1980              : dummy_tmp_1,    & ! B matrix
    1981              : lsolutions,    & ! leading dimension of B
    1982              : cmplx_1,    & ! beta  is one
    1983              : projected_dielectric_Lanczos_basis(:,:,iw),    & ! C matrix
    1984          280 : lmax)      ! leading dimension of C
    1985              : 
    1986          280 : ABI_FREE(dummy_tmp_1)
    1987              : 
    1988          280 : call cpu_time(time2)
    1989          308 : time_exact = time_exact + time2-time1
    1990              : 
    1991              : end do ! iw
    1992              : 
    1993           28 : write(io_unit_log,10) '   - Deallocate tmp arrays...'
    1994           28 : flush(io_unit_log)
    1995              : 
    1996              : 
    1997              : 
    1998              : 
    1999           28 : ABI_FREE(ipiv           )
    2000           28 : ABI_FREE(sternheimer_A  )
    2001           28 : ABI_FREE(sternheimer_A0 )
    2002           28 : ABI_FREE(sternheimer_B  )
    2003           28 : ABI_FREE(sternheimer_X  )
    2004           35 : ABI_FREE(sternheimer_G  )
    2005              : 
    2006              : end do ! v
    2007              : 
    2008              : !--------------------------------------------------------------------------
    2009              : ! Finalize, post v loop
    2010              : !--------------------------------------------------------------------------
    2011            7 : write(io_unit_log,10) " - Finalize, after band iterations...."
    2012            7 : flush(io_unit_log)
    2013              : 
    2014              : 
    2015              : 
    2016              : 
    2017              : 
    2018            7 : timing_string = "#        Exact Sector :   "
    2019            7 : call write_timing_log(timing_string,time_exact)
    2020              : 
    2021              : 
    2022           28 : ABI_MALLOC(dummy_tmp_1,(lmax,lmax))
    2023           21 : ABI_MALLOC(dummy_tmp_2,(lmax,lmax))
    2024              : 
    2025           77 : do iw = 2, npt_gauss+1
    2026              : ! finally, make sure matrix is hermitian
    2027              : 
    2028              : ! play this little game to avoid STACK problems
    2029         5110 : dummy_tmp_1(:,:) = 0.5_dp*transpose(projected_dielectric_Lanczos_basis(:,:,iw))
    2030         5110 : dummy_tmp_2(:,:) = conjg(dummy_tmp_1(:,:))
    2031         5110 : dummy_tmp_1(:,:) = dummy_tmp_2(:,:) +0.5_dp*projected_dielectric_Lanczos_basis(:,:,iw)
    2032              : 
    2033         5117 : projected_dielectric_Lanczos_basis(:,:,iw) =    dummy_tmp_1(:,:)
    2034              : end do
    2035              : 
    2036            7 : ABI_FREE(dummy_tmp_1)
    2037            7 : ABI_FREE(dummy_tmp_2)
    2038              : 
    2039              : 
    2040              : 
    2041            7 : if ( write_debug ) then
    2042              :   !write some results to a file
    2043              : 
    2044            0 :   write(io_unit,10) '#===================================================================================================='
    2045            0 :   write(io_unit,10) "#                     Projected dielectric matrices                                                  "
    2046            0 :   write(io_unit,10) "#                     -------------------------------------------------------                        "
    2047            0 :   write(io_unit,10) "# This file contains the various projected dielectric matrices as a function of frequency.           "
    2048            0 :   write(io_unit,10) '#===================================================================================================='
    2049            0 :   write(io_unit,10) ''
    2050            0 :   flush(io_unit)
    2051              : 
    2052            0 :   do iw = 1, npt_gauss+1
    2053            0 :   write(io_unit,10) "#"
    2054            0 :   write(io_unit,12) "# omega = ",list_omega(iw), " i Ha"
    2055            0 :   write(io_unit,10) "#"
    2056              : 
    2057            0 :   do l =1, lmax
    2058            0 :   write(io_unit,30)  projected_dielectric_Lanczos_basis(l,:,iw)
    2059              :   end do
    2060              :   end do
    2061              : 
    2062              : end if
    2063              : 
    2064              : 
    2065            7 : if ( model ) then
    2066              : 
    2067              : 
    2068              :   ! Add all components on the processors
    2069            6 :   call xmpi_sum(model_dielectric_Lanczos_basis,mpi_communicator,ierr) ! sum on all processors
    2070              : 
    2071              :   ! add the identity
    2072           72 :   do iw = 1, npt_gauss+1
    2073          600 :   do l= 1, lmax
    2074          594 :   model_dielectric_Lanczos_basis(l,l,iw) = model_dielectric_Lanczos_basis(l,l,iw) + cmplx_1
    2075              :   end do
    2076              :   end do
    2077              : 
    2078              :   ! hermitian the operator
    2079           72 :   do iw = 1, npt_gauss+1
    2080              : 
    2081          600 :   do l1 = 1, lmax
    2082         2970 :   do l2 = 1, l1
    2083              :   ! operator is hermitian
    2084         2904 :   model_dielectric_Lanczos_basis(l2,l1,iw) = conjg(model_dielectric_Lanczos_basis(l1,l2,iw))
    2085              :   end do
    2086              :   end do
    2087              : 
    2088              :   end do ! iw
    2089              : 
    2090              : end if
    2091              : 
    2092              : 
    2093              : 
    2094            7 : if ( write_debug ) then
    2095            0 :   close(io_unit)
    2096              : end if
    2097              : 
    2098            7 : write(io_unit_log,10) " - Deallocate and exit...."
    2099            7 : flush(io_unit_log)
    2100              : 
    2101              : 
    2102              : 
    2103            7 : if (debug) then
    2104            0 :   ABI_FREE(check_matrix)
    2105            0 :   ABI_FREE(check_matrix2)
    2106              : end if
    2107              : 
    2108              : 
    2109            7 : ABI_FREE(psikg_valence)
    2110            7 : ABI_FREE(psir_valence)
    2111            7 : ABI_FREE(psikg_VL)
    2112              : 
    2113              : 
    2114            7 : ABI_FREE(YL)
    2115              : 
    2116            7 : ABI_FREE(local_Lbasis_conjugated)
    2117            7 : ABI_FREE(local_Lbasis)
    2118              : 
    2119              : 
    2120            7 : ABI_FREE(svd_matrix)
    2121            7 : ABI_FREE(svd_values)
    2122            7 : ABI_FREE(psi_gamma_l1)
    2123            7 : ABI_FREE(psi_gamma_l2)
    2124              : 
    2125            7 : ABI_FREE(psikg_in)
    2126            7 : ABI_FREE(psikg_out)
    2127              : 
    2128            7 : ABI_FREE(psi_rhs)
    2129              : 
    2130            7 : ABI_FREE(c_sternheimer_solutions)
    2131            7 : ABI_FREE(QR_orthonormal_basis)
    2132              : 
    2133            7 : ABI_FREE(psik_wrk)
    2134            7 : ABI_FREE(psikb_wrk)
    2135            7 : ABI_FREE(psikg_wrk)
    2136              : 
    2137              : 
    2138            7 : close(io_unit_log)
    2139              : 
    2140              : 
    2141              : 10 format(A)
    2142              : 12 format(A,F12.8,A)
    2143              : 14 format(I5,10X,ES24.12)
    2144              : 15 format(I5,10X,ES24.12,10X,A)
    2145              : 
    2146              : 19 format(20X,A,15X,E24.16)
    2147              : 
    2148              : 20 format(A,I5)
    2149              : 21 format(I5,10X,F8.4,15X,ES24.12)
    2150              : 22 format(A,I5,A)
    2151              : 23 format(A,I5,A,I5)
    2152              : 30 format(2X,1000(ES12.4,2X,ES12.4,5X))
    2153              : 
    2154            7 : end subroutine ProjectedSternheimerEpsilon
    2155              : !!***
    2156              : 
    2157              : 
    2158              : end module m_gwls_DielectricArray
    2159              : !!***
        

Generated by: LCOV version 2.3-1