! ! License-Identifier: GPL ! ! Copyright (C) 2007 The Yambo Team ! ! Authors (see AUTHORS file for details): AM DS ! ! headers ! #include<y_memory.h> ! subroutine K_inversion_driver(iq,W,E,k,q) ! use pars, ONLY:SP use X_m, ONLY:Resp_ii,X_OUTPUT_driver use BS_solvers, ONLY:BSS_inversion_mode,BSS_desc,K_INV_PL,K_INV_EPS,& & K_Inversion_data,K_slk,K_inv_slk use BS, ONLY:BS_H_dim,BS_Blocks_symmetrize_K,BS_blk,l_BS_ares_from_res,& & BS_K_anti_resonant,l_BS_photolum,BS_res_ares_n_mat use electrons, ONLY:levels use frequency, ONLY:w_samp use R_lattice, ONLY:bz_samp use com, ONLY:isec,msg use LIVE_t, ONLY:live_timing use parallel_int, ONLY:PP_wait,PP_redux_wait,PARALLEL_index,PARALLEL_live_message use parallel_m, ONLY:PP_indexes,PP_indexes_reset,PAR_COM_SLK_INDEX_local,PAR_COM_SLK_INDEX_local,& & CPU_structure use linear_algebra, ONLY:INV use IO_int, ONLY:io_control use IO_m, ONLY:REP,NONE,OP_WR_CL use matrix, ONLY:MATRIX_reset use timing_m, ONLY:timing use BS_solvers, ONLY:BS_mat use interfaces, ONLY:K_stored_in_a_big_matrix #if defined _SCALAPACK use interfaces, ONLY:MATRIX_transfer,MATRIX_duplicate use parallel_m, ONLY:linear_algebra_is_parallel #endif #if defined _RT use RT_control, ONLY:NEQ_Residuals,NEQ_Kernel #endif use stderr, ONLY:intc use descriptors, ONLY:IO_desc_add use PHOTOLUM, ONLY:BSS_PL_free,PL use y_memory_alloc ! implicit none ! type(w_samp) :: W integer :: iq type(levels) :: E type(bz_samp):: k,q ! ! Work Space... ! ! ... dummies ! type(PP_indexes) :: PAR_IND_freqs integer :: i1,i2,iw,PAR_IND_FREQ_ID logical, external :: STOP_now real(SP) :: ratio character(1) :: sec complex(SP), allocatable :: Lo(:,:,:) ! ! ... frequencies ! integer ::nw,nw_conv logical ::FULL,PERTURBATIVE,completed ! ! I/O ! integer :: i_err,ID,Lo_dim integer, external :: io_BSS_invert ! if (BS_res_ares_n_mat>1) then call warning(" inversion solver coding not finalized for case with two BSE matricies ") return endif ! call timing('Inversion Solver',OPR='start') ! call PARALLEL_assign_LA_COMMs("Response_T_space",INV,CPU_structure(4)%nCPU_lin_algebra_INV) ! ! Sectioning !============ if (isec(2)/=0) sec="=" if (isec(2)==0) sec="+" call section(sec,'Inversion Solver @q'//trim(intc(iq))) ! #if defined _SCALAPACK ! ! Symmetrize the K blocks (to be eventually sent to the BLACS) !========================= if (linear_algebra_is_parallel) call BS_Blocks_symmetrize_K() ! #endif ! ! Restart database !================== call K_inversion_restart(iq,W) ! completed=count(K_INV_EPS%err/=0)==0 if(l_BS_photolum) completed=completed.and.count(K_INV_PL%err/=0)==0 if (completed) then call LOCAL_clean() return endif ! ! Full inversion ? !================== FULL = index(BSS_inversion_mode,'f')/=0 PERTURBATIVE = index(BSS_inversion_mode,'p')/=0 ! #if defined _RT if (NEQ_Residuals.neqv.NEQ_Kernel) then call warning("[INV] Different occupation configurations for Kernel and Residuals not supported") endif #endif ! #if defined _SCALAPACK ! ! SLK matrix initialization before the Kernel loading ! call MATRIX_init( "SLK", K_slk, BS_H_dim, 1 ) ! YAMBO_ALLOC(K_slk%blc,(K_slk%BLCrows(1):K_slk%BLCrows(2),K_slk%BLCcols(1):K_slk%BLCcols(2),1)) ! #endif ! ! Kernel and/or BSS components loading !====================================== call K_components_folded_in_serial_arrays(iq) ! if (K_slk%kind=="SLK") then ! #if defined _SCALAPACK ! call msg('rs','[LA] BLACS matrix filling') ! ! Prepare the BLACS matrices (reference, K_slk and local, K_inv_slk) !============================ ! call MATRIX_transfer(M_out=K_slk, M_bse= BS_blk ) ! ! Diagonal removal !================== call K_diagonal(iq,"rm_OCC DIAG") ! if (FULL) call MATRIX_duplicate( "none", M_in=K_slk, M_out=K_inv_slk ) ! #endif ! else ! call K_stored_in_a_big_matrix(1,BS_H_dim,BS_mat,iq,"INV") ! ! Diagonal removal !================== call K_diagonal(iq,"rm_E rm_OCC DIAG") ! endif ! ! IP-part Lo [also recompute Resp_xx(:,3) OR PL (needed in case of DbG)] !=========================================================================== Lo_dim=1 if (BS_K_anti_resonant.and.l_BS_ares_from_res) Lo_dim=2 ! ! In the PL case we need, in addition to the standard GF, also some additional L_k^(r)(w) A_k(w) L_k^(a)(w), where ! L^(a/r) are deduced from the standard components. ! if (l_BS_photolum) then Lo_dim=2 if (BS_K_anti_resonant.and.l_BS_ares_from_res) Lo_dim=4 endif ! YAMBO_ALLOC(Lo,(BS_H_dim,W%n_freqs,Lo_dim)) ! call K_inversion_Lo(iq,W,E,k,Lo_dim,Lo) ! ! Initialize & write the output file !==================================== call X_OUTPUT_driver("DEF INIT",solver="Inversion") call K_OUTPUT(iq,W,"open Inversion close","ALL") ! ! Perturbative Inversion !======================== call PP_indexes_reset(PAR_IND_freqs) PAR_IND_FREQ_ID=PAR_COM_SLK_INDEX_local%CPU_id+1 ! if (PERTURBATIVE) then ! call PARALLEL_index(PAR_IND_freqs,(/W%n_freqs/),COMM=PAR_COM_SLK_INDEX_local) call PARALLEL_live_message('Perturbative Inversion Frequencies',LOADED=PAR_IND_freqs%n_of_elements(PAR_IND_FREQ_ID),& & TOTAL=W%n_freqs,NCPU=PAR_COM_SLK_INDEX_local%n_CPU) call live_timing('Perturbative inversion ',PAR_IND_freqs%n_of_elements(PAR_IND_FREQ_ID)) ! call K_inversion_engine("any",1,W%n_freqs,PAR_IND_freqs,W,Lo,Lo_dim,.FALSE.) ! call PP_redux_wait(K_INV_EPS%err,COMM=PAR_COM_SLK_INDEX_local%COMM) call PP_redux_wait(Resp_ii(:,2),COMM=PAR_COM_SLK_INDEX_local%COMM) if (l_BS_photolum) then call PP_redux_wait(K_INV_PL%err,COMM=PAR_COM_SLK_INDEX_local%COMM) call PP_redux_wait(PL(:,2),COMM=PAR_COM_SLK_INDEX_local%COMM) endif ! ! I/O [after pert inversion] ! K_INV_EPS%spectra(:,1)=Resp_ii(:,2) if (l_BS_photolum) then K_INV_PL%spectra(:,1)=cmplx(PL(:,2),0._SP,kind=SP) ! call io_control(ACTION=OP_WR_CL,COM=NONE,SEC=(/1,2,3,4/),ID=ID) i_err=io_BSS_invert(iq,W,ID) call msg('rs','[PERTURBATIVE INV@PL ] Converged frequencies ',count(K_INV_PL%err==0)) else call io_control(ACTION=OP_WR_CL,COM=NONE,SEC=(/1,2,3/),ID=ID) i_err=io_BSS_invert(iq,W,ID) call msg('rs','[PERTURBATIVE INV@EPS] Converged frequencies ',count(K_INV_EPS%err==0)) endif ! endif ! call K_OUTPUT(iq,W,"override dump Inversion close","ALL") ! ! Full Inversion !================= ! ! First I define the group of frequencies not converged ! if (FULL) then !====== call FULL_INF_freqs(K_INV_EPS) if (l_BS_photolum) call FULL_INF_freqs(K_INV_PL) ! endif ! if (FULL.and.PERTURBATIVE) then !============== ! call FULL_INF_pre_setup(K_INV_EPS) if (l_BS_photolum) call FULL_INF_pre_setup(K_INV_PL) ! endif ! ! FULL INVERSION !================ ! if (K_INV_EPS%n_full_inv_freqs>0.and.FULL) call do_it_FULL(K_INV_EPS) if (l_BS_photolum) then if (K_INV_PL%n_full_inv_freqs>0.and.FULL) call do_it_FULL(K_INV_PL) endif ! ! Try a polinomial interpolation on the null values (only for EPS) !================================================================== call K_eps_interpolate(W%n_freqs,real(W%p),K_INV_EPS%err) ! call PP_wait() ! ! I/O [after full inversion] !===== K_INV_EPS%spectra(:,1)=Resp_ii(:,2) if (l_BS_photolum) K_INV_PL%spectra(:,1)=cmplx(PL(:,2),0._SP,kind=SP) ! if (l_BS_photolum) then call io_control(ACTION=OP_WR_CL,COM=REP,SEC=(/1,2,3,4/),ID=ID) i_err=io_BSS_invert(iq,W,ID) else call io_control(ACTION=OP_WR_CL,COM=REP,SEC=(/1,2,3/),ID=ID) i_err=io_BSS_invert(iq,W,ID) endif ! ! Final Output !============== ! ratio=real(count(K_INV_EPS%err==0))/real(W%n_freqs)*100._SP ! call IO_desc_add(BSS_desc,kind="r",str="[INV] Converged frequencies",term="o/o",R=(/ratio/)) ! call K_OUTPUT(iq,W,"override dump close Inversion","ALL") ! ! CLEAN ! call LOCAL_clean() ! contains ! subroutine do_it_FULL(TYP) ! type(K_Inversion_data) :: TYP ! ! Then loop on the groups performing full inversion ! call PP_indexes_reset(PAR_IND_freqs) call PARALLEL_index(PAR_IND_freqs,(/TYP%n_full_inv_freqs/),COMM=PAR_COM_SLK_INDEX_local) call PARALLEL_live_message('['//TYP%what//'] Exact Inversion Frequencies',LOADED=PAR_IND_freqs%n_of_elements(PAR_IND_FREQ_ID),& & TOTAL=TYP%n_full_inv_freqs,NCPU=PAR_COM_SLK_INDEX_local%n_CPU) call live_timing('['//TYP%what//'] Exact inversion ',PAR_IND_freqs%n_of_elements(PAR_IND_FREQ_ID)) ! do i1=1,TYP%n_full_inv_freqs ! if (.not.PAR_IND_freqs%element_1D(i1)) cycle ! iw=TYP%iw_full(i1) ! call K_inversion_engine(TYP%what,iw,1,PAR_IND_freqs,W,Lo,Lo_dim,.TRUE.) ! call live_timing(steps=1) ! if (STOP_now(.FALSE.)) then exit endif ! enddo ! call live_timing() call PP_redux_wait(TYP%err,imode=2) if (TYP%what=="EPS") call PP_redux_wait(Resp_ii(:,2),COMM=PAR_COM_SLK_INDEX_local%COMM) if (TYP%what=="PLS") call PP_redux_wait(PL(:,2),COMM=PAR_COM_SLK_INDEX_local%COMM) ! nw_conv=count(TYP%err==0) call msg('rs','[FULL INV@'//TYP%what//'] Frequencies DONE ',nw_conv) call msg('rs','[FULL INV@'//TYP%what//'] ',real(nw_conv)/real(W%n_freqs)*100._SP,"[o/o]") ! end subroutine ! subroutine FULL_INF_freqs(TYP) type(K_Inversion_data) :: TYP TYP%n_full_inv_freqs=0 do i1=1,W%n_freqs if (TYP%err(i1)/=0) then TYP%n_full_inv_freqs=TYP%n_full_inv_freqs+1 TYP%iw_full(TYP%n_full_inv_freqs)=i1 endif enddo end subroutine ! subroutine FULL_INF_pre_setup(TYP) ! type(K_Inversion_data) :: TYP integer :: min_dist_non_conv_freqs ! Every W%n_freqs/min_dist_non_conv_freqs logical :: found ! min_dist_non_conv_freqs=W%n_freqs found = .FALSE. ! do while (.not.found) ! TYP%n_full_inv_freqs=0 ! iw=-1 nw=0 do i1=1,W%n_freqs if (TYP%err(i1)/= 0.and.iw<0) iw=i1 if (TYP%err(i1)/= 0.and.iw>0) nw=nw+1 if ((TYP%err(i1)== 0.or.(TYP%err(i1)/=0.and.i1==W%n_freqs)).and.iw>0) then ! if (nw>=min_dist_non_conv_freqs) then ! do i2=iw,iw+nw-1,min_dist_non_conv_freqs TYP%n_full_inv_freqs=TYP%n_full_inv_freqs+1 TYP%iw_full(TYP%n_full_inv_freqs)=i2 enddo ! endif iw=-1 nw=0 endif enddo min_dist_non_conv_freqs=min_dist_non_conv_freqs-1 if (min_dist_non_conv_freqs==0) found=.TRUE. ! if (TYP%n_full_inv_freqs>=nint(real(W%n_freqs)/TYP%PERT_FULL_ratio)) found=.TRUE. ! enddo ! if (TYP%n_full_inv_freqs>0.and.FULL) then if (TYP%what=="EPS") Resp_ii(:,2)=Resp_ii(:,2)/real(PAR_COM_SLK_INDEX_local%n_CPU,SP) if (TYP%what=="PLS") PL(:,2)=PL(:,2)/real(PAR_COM_SLK_INDEX_local%n_CPU,SP) endif ! call msg('rs','[FULL INV@'//TYP%what//'] Frequencies TODO ',TYP%n_full_inv_freqs) ! end subroutine ! subroutine LOCAL_clean ! if (l_BS_photolum) call BSS_PL_free( ) ! call LOCAL_TYP_clean(K_INV_EPS) if (l_BS_photolum) call LOCAL_TYP_clean(K_INV_PL) ! call PP_indexes_reset(PAR_IND_freqs) YAMBO_FREE(Lo) ! #if defined _SCALAPACK YAMBO_FREE(K_slk%blc) call MATRIX_reset(K_slk) ! ! Here I call MATRIX_duplicate instead of a simple YAMBO_FREE to keep the correct naming ! to be used in the memory module ! call MATRIX_duplicate( "free", M_out=K_inv_slk ) #endif ! call timing('Inversion Solver',OPR='stop') end subroutine ! subroutine LOCAL_TYP_clean(TYP) type(K_Inversion_data) :: TYP deallocate(TYP%err,TYP%spectra,TYP%iw_full) end subroutine ! end subroutine