! ! License-Identifier: GPL ! ! Copyright (C) 2006 The Yambo Team ! ! Authors (see AUTHORS file for details): AM DS ! ! headers ! #include<y_memory.h> ! subroutine bz_samp_indexes(en,k,Xk,q) ! ! ikbz=(ik,is) --<--:--<-- okbz=(ok,os) = (IK-Q) ! : ! /:\ iqbz=(iq,is) ! : ! ! iq_is = ik_is-ok_os-Go ! ! qindx_X(iq,ikbz,1)=okbz ! qindx_X(iq,ikbz,2)=iGo ! ! qindx_B(okbz,ikbz,1)=iqbz ! qindx_B(okbz,ikbz,2)=iGo ! ! qindx_S(ik,iqbz,1)=okbz ! qindx_S(ik,iqbz,2)=iGo ! ! qindx_C(ikbz,iqbz,1)=okbz ! qindx_C(ikbz,iqbz,2)=iGo ! use pars, ONLY:SP,schlen,lchlen,zero_dfl use drivers, ONLY:l_bse,l_elel_scatt,l_setup,l_nl_optics,l_EXCPH_gkkp use com, ONLY:msg,fat_log use parallel_m, ONLY:PAR_K_scheme,master_cpu,PP_indexes,myid,PP_indexes_reset use parallel_int, ONLY:PP_wait,PP_redux_wait,PARALLEL_index,PARALLEL_global_indexes use LIVE_t, ONLY:live_timing use matrix_operate, ONLY:m3inv,m3det use electrons, ONLY:n_sp_pol,levels use vec_operate, ONLY:v_is_zero,c2a use BS, ONLY:BS_res_K_corr,BS_cpl_K_corr use R_lattice, ONLY:d3q_factor,RL_vol,nqibz,nqbz,QP_states_k,& & qindx_X,qindx_B,qindx_S,qindx_C,qindx_free,& & bse_scattering,qindx_alloc,Xk_grid_is_uniform,& & k_grid,k_grid_b,q_pt,k_pt,bz_samp,q_norm,q0_def_norm,& & q_sstar,coll_scattering,q_source,smallest_q_norm,qindx_S_max_Go,& & Xk_grid_new_mapping,X_scattering,sigma_scattering,& & k_GRIDS_string,k_GRIDS_vector use IO_int, ONLY:io_control use IO_m, ONLY:OP_RD_CL,OP_WR_CL,OP_APP_CL,VERIFY,REP use parser_m, ONLY:parser use timing_m, ONLY:timing use openmp, ONLY:n_threads,master_thread,OPENMP_update #if defined _ELPH use ELPH, ONLY:elph_use_q_grid #endif use y_memory_alloc ! implicit none ! type(levels), intent(in) :: en type(bz_samp), intent(inout) :: k,Xk,q ! ! Work Space ! integer :: io_db,io_err,n_mapped,n_not_mapped integer :: i1,i2,i3,i4,iv1(3),iqibz,iqbz,ikibz,ikbz,ikbz_p,ikbz_mem,iqs,iks,id real(SP):: v1(3),k_b_m1(3,3),local_zero(3),q_step(3) real(SP):: E_empty(1,q%nibz,n_sp_pol) logical :: connected_grids,user_defined_qpts,user_grids,do_qindx_B,do_qindx_X,do_qindx_X_ik #if defined _ELPH logical :: bse_setup_scatt #endif character(schlen) :: convention integer, external :: G_index character(lchlen) :: string(2) integer, allocatable :: q_map(:,:,:),q_iptbz(:,:) type(PP_indexes) :: PAR_IND_Xk,PAR_IND_k integer, external :: io_QINDX integer, external :: io_kpts ! call section('*','Transferred momenta grid and indexing') !======================================================== ! .... defaults X_scattering =.true. sigma_scattering=.true. bse_scattering =(l_bse .and. (BS_res_K_corr.or.BS_cpl_K_corr)) coll_scattering =(l_elel_scatt.or.l_EXCPH_gkkp) convention="minus_q" ! ! ... User defined ! #if defined _ELPH call parser('BSEscatt',bse_setup_scatt) call warning(' BSE and COLL scattering equal to TRUE') ! if (.not.bse_scattering ) bse_scattering =elph_use_q_grid.or.bse_setup_scatt.or.trim(q_source)=="Electron-Phonon databases" bse_scattering=.TRUE. coll_scattering=.TRUE. #endif ! #if defined _NL ! ! In the non-linear spectroscoy I don't load qindx_X and qindx_S ! if(l_nl_optics) then X_scattering =.FALSE. ! sigma_scattering=.FALSE. ! I need them for the LSEX endif ! #endif ! call parser('K_grids', user_grids) if (user_grids) then bse_scattering= index(k_GRIDS_string,"B")/=0 coll_scattering= index(k_GRIDS_string,"C")/=0 X_scattering= index(k_GRIDS_string,"X")/=0 sigma_scattering=index(k_GRIDS_string,"S")/=0 if (index(k_GRIDS_string,"plus_q")/=0) convention="plus_q" endif ! ! ... some over-rule needed if (bse_scattering) X_scattering =.TRUE. if (coll_scattering) sigma_scattering=.TRUE. ! ! ... update string call k_GRIDS_update( ) ! q%description='q' ! !call io_control(ACTION=OP_RD_CL,COM=REP,SEC=(/1/),MODE=VERIFY,ID=io_db) !io_err=io_kpts(k,Xk,q,io_db) !! !if (io_err/=0) then ! call io_control(ACTION=OP_WR_CL,COM=REP,SEC=(/1,2/),MODE=VERIFY,ID=io_db) ! io_err=io_kpts(k,Xk,q,io_db) !endif ! call io_control(ACTION=OP_RD_CL,COM=REP,SEC=(/1,2,3,4,6/),MODE=VERIFY,ID=io_db) io_err=io_QINDX(Xk,q,io_db,trim(convention)) ! if (io_err==0) then call k_expand(q) d3q_factor=RL_vol/real(q%nbz) if(l_setup.and.fat_log) call print_q_indirect( ) call REPORT_Energies(E_empty,q,q,1,(/1,q%nibz/),'Q',.TRUE.,.FALSE.) call q_shadows(.false.) return endif ! call timing('bz_samp_indexes',OPR='start') ! ! First I map the Xk grid in a simple cubic Net ! call k_ibz2bz(Xk,'a',.false.) ! ! Parallelization without Memory distribution !============================================= ! call PP_indexes_reset(PAR_IND_Xk) call PARALLEL_index(PAR_IND_Xk,(/Xk%nbz/)) call PP_indexes_reset(PAR_IND_k) call PARALLEL_index(PAR_IND_k,(/k%nbz/)) ! YAMBO_ALLOC(q_map,(k_grid(1),k_grid(2),k_grid(3))) YAMBO_ALLOC(q_iptbz,(Xk%nbz,3)) ! ! k_b_m1=transpose(k_grid_b) in rlu ! ! k_grid_b is in cc ! ! call c2a(v_in=k_grid_b(1,:),v_out=k_b_m1(:,1),mode='kc2a') call c2a(v_in=k_grid_b(2,:),v_out=k_b_m1(:,2),mode='kc2a') call c2a(v_in=k_grid_b(3,:),v_out=k_b_m1(:,3),mode='kc2a') ! ! q_iptbz(i,:) = Xk%ptbz(1,:) - Vo in units of k_grid_b ! q_map gives the index of q_iptbz given the components along k_grid_b ! ! As first step I define the map with respect to Q defined as difference ! of K-pts ! if (abs(m3det(k_b_m1))>1.E-7) then ! call m3inv(M=k_b_m1) ! if( Xk_grid_new_mapping) call define_q_map_new( Xk%ptbz(:,:), Xk%ptbz(1,:)) if(.not.Xk_grid_new_mapping) call define_q_map ( Xk%ptbz(:,:), Xk%ptbz(1,:)) ! ! THE GRID IS UNIFORM IF ALL THE Q_MAP IS FILLED ! n_mapped=count(q_map/=0) n_not_mapped=count(q_map==0) ! call msg("sr","[BZ sampling] q_map (mappend, not mapped)",(/n_mapped,n_not_mapped/)) ! Xk_grid_is_uniform=(n_not_mapped==0) ! else Xk_grid_is_uniform=.false. endif ! user_defined_qpts=.false. ! if (Xk_grid_is_uniform) then ! q%nbz=Xk%nbz ! ! q_ptbz in iku for k_reduce ! YAMBO_ALLOC(q%ptbz,(q%nbz,3)) do i1=1,q%nbz ! v1=Xk%ptbz(i1,:)-Xk%ptbz(1,:) ! call c2a(v_in= v1,v_out=q%ptbz(i1,:),mode='ka2i') ! enddo if (.not.allocated(q_pt)) then call k_reduce(q,.TRUE.) YAMBO_FREE(q%ptbz) else q%nibz=nqibz YAMBO_ALLOC(q%pt,(q%nibz,3)) q%pt=q_pt(:q%nibz,:) call msg('rsn','[BZ sampling] Q-grid '//trim(q_source)) user_defined_qpts=.true. endif ! ! q_ptbz in rlu for qindx_*. ! At difference with the Q list used in evaluating the map before ! here I need to recalculate the map so that it correctly points ! to the q%ptbz obtaine trought q_expand ! call k_expand(q) call q_shadows(.false.) call k_ibz2bz(q,'a',.false.) nqbz =q%nbz nqibz=q%nibz call REPORT_Energies(E_empty,q,q,1,(/1,q%nibz/),'Q',.TRUE.,.FALSE.) ! ! When using USER defined Q-points q%nbz may be different from Xk%nbz ! if the given list is not correct. ! In this case I switch to the Gamma only support ! if (q%nbz/=Xk%nbz) then call bz_X_only_exit('[RL indx] Q BZ pts are /= from X grid BS pts. Gamma point only.') else if( Xk_grid_new_mapping) call define_q_map_new(q%ptbz(:,:),(/0._SP,0._SP,0._SP/)) if(.not.Xk_grid_new_mapping) call define_q_map (q%ptbz(:,:),(/0._SP,0._SP,0._SP/)) endif ! else ! call bz_X_only_exit('[RL indx] X grid is not uniform. Gamma point only.') ! endif ! d3q_factor=RL_vol/real(q%nbz) ! ! X indexes ! ! qindx_X(iq,ikbz,1)=okbz ! qindx_X(iq,ikbz,2)=iGo ! ! qindx_B(okbz,ikbz,1)=iqbz ! qindx_B(okbz,ikbz,2)=iGo ! if (X_scattering) string(1)='X' if (sigma_scattering) string(2)='Sigma' if ( bse_scattering) string(1)=trim(string(1))//' + BSE' if (coll_scattering) string(2)=trim(string(2))//' + COLL' ! #if defined _PAR_IO ! ! Parallelization with Memory distribution !========================================== if(X_scattering.and.Xk_grid_is_uniform.and.bse_scattering) then call PARALLEL_global_indexes(en,Xk,q,"BZ_Indexes") call PARALLEL_SETUP_K_scheme("BZINDX") endif ! #endif ! if (X_scattering.and.Xk_grid_is_uniform) then ! ! Allocate ! call qindx_alloc('XB') ! call section('+',trim(string(1))//' indexes') !============================================ ! ! X/BSE !------ call live_timing(trim(string(1))//' [eval]',max(1,PAR_IND_Xk%n_of_elements(myid+1)/n_threads)) ! if (Xk_grid_new_mapping) call k_find_smallest_q(Xk%ptbz,q_step,Xk%nbz) ! !$omp parallel default(shared), private(ikbz,ikbz_mem,ikbz_p,v1,iv1,iqbz,iqibz,iqs,do_qindx_B,do_qindx_X,do_qindx_X_ik) call OPENMP_update(master_thread) ! !$omp do do ikbz=1,Xk%nbz ! do_qindx_X_ik=PAR_IND_Xk%element_1D(ikbz) do_qindx_B =PAR_IND_Xk%element_1D(ikbz).and.bse_scattering ikbz_mem=ikbz ! #if defined _PAR_IO if(bse_scattering) then do_qindx_B=PAR_K_scheme%IND_bz%element_1D(ikbz) ikbz_mem=PAR_K_scheme%bz_index(ikbz) endif #endif ! if ((.not.do_qindx_X_ik).and.(.not.do_qindx_B)) cycle ! do ikbz_p=1,Xk%nbz ! if (trim(convention)=="minus_q") v1=Xk%ptbz(ikbz,:)-Xk%ptbz(ikbz_p,:) ! K-K_p= Q + Go if (trim(convention)=="plus_q" ) v1=Xk%ptbz(ikbz_p,:)-Xk%ptbz(ikbz,:) ! K_p-K= Q + Go ! if(Xk_grid_new_mapping) then ! v1=v1-nint(v1) ! Bring in the BZ, remove the G0 where(v1<-zero_dfl) ! Bring between [0,1) v1(:)=1._SP+v1(:) end where do id=1,3 if(q_step(id)==0) then iv1(id)=1 ! Non-periodic directions or no kpoints in this direction else iv1(id)=nint(v1(id)/q_step(id))+1 endif enddo ! else ! v1=matmul(k_b_m1,v1) iv1=nint(v1) call k_grid_shift(iv1) ! endif ! iqbz =q_map(iv1(1),iv1(2),iv1(3)) iqibz=q%sstar(iqbz,1) iqs =q%sstar(iqbz,2) ! do_qindx_X=do_qindx_X_ik .and. iqs==1 ! if ((.not.do_qindx_X).and.(.not.do_qindx_B)) cycle ! if (do_qindx_X) qindx_X(iqibz,ikbz,1)=ikbz_p if (do_qindx_B) qindx_B(ikbz_p,ikbz_mem,1)=iqbz ! if (trim(convention)=="minus_q") v1=Xk%ptbz(ikbz,:)-Xk%ptbz(ikbz_p,:)-q%ptbz(iqbz,:) if (trim(convention)=="plus_q" ) v1=Xk%ptbz(ikbz_p,:)-Xk%ptbz(ikbz,:)-q%ptbz(iqbz,:) call c2a(v_in=v1,mode='ka2i') ! if (do_qindx_X) qindx_X(iqibz, ikbz ,2)=G_index(v1,.true.) if (do_qindx_B) qindx_B(ikbz_p,ikbz_mem,2)=G_index(v1,.false.) ! if ( do_qindx_X .and. qindx_X(iqibz,ikbz,2)==0 ) exit ! enddo ! if (master_thread) call live_timing(steps=1) ! enddo !$omp end do !$omp end parallel ! call live_timing() ! ! ... PARALLEL redux call live_timing(trim(string(1))//'[REDUX]',Xk%nbz) do ikbz=1,Xk%nbz call PP_redux_wait(qindx_X(:,ikbz,1)) call PP_redux_wait(qindx_X(:,ikbz,2)) #if !defined _PAR_IO if (bse_scattering) then call PP_redux_wait(qindx_B(:,ikbz,1)) call PP_redux_wait(qindx_B(:,ikbz,2)) endif #endif call live_timing(steps=1) enddo call live_timing() ! if (any(qindx_X==0)) then call bz_X_only_exit('Null transition detected [qindx_X]. Gamma point only.') endif ! endif ! ! SIGMA/COLL !------------ if (sigma_scattering) then ! call section('+',trim(string(2))//' indexes') !============================================ ! if( coll_scattering) i1=Xk%nbz if(.not.coll_scattering) i1=QP_states_k(2)-QP_states_k(1)+1 ! call live_timing(trim(string(2))//' [eval]',max(1,i1/n_threads)) ! call k_ibz2bz(k,'a',.false.) ! connected_grids=.true. local_zero=1.E-4_SP ! call qindx_alloc('SC') ! ! qindx_S(ik,iqbz,1)=okbz ! qindx_S(ik,iqbz,2)=iGo ! ! qindx_C(ikbz,iqbz,1)=okbz ! qindx_C(ikbz,iqbz,2)=iGo ! !$omp parallel default(shared), private(ikbz,ikibz,iks,ikbz_p,v1,iv1,iqbz) call OPENMP_update(master_thread) ! !$omp do do ikbz=1,k%nbz ! ikibz=k%sstar(ikbz,1) iks =k%sstar(ikbz,2) ! if (iks/=1.and..not.coll_scattering) cycle ! do ikbz_p=1,k%nbz ! if (.not.PAR_IND_k%element_1D(ikbz_p)) cycle ! if (trim(convention)=="minus_q") v1=k%ptbz(ikbz,:)-k%ptbz(ikbz_p,:) ! K-K_p= Q + Go if (trim(convention)=="plus_q" ) v1=k%ptbz(ikbz_p,:)-k%ptbz(ikbz,:) ! K_p-K= Q + Go ! if(Xk_grid_new_mapping) then ! v1=v1-nint(v1) ! Bring in the BZ, remove the G0 where(v1<-zero_dfl) ! Bring between [0,1) v1(:)=1._SP+v1(:) end where do id=1,3 if(q_step(id)==0) then iv1(id)=1 ! Non-periodic directions or no kpoints in this direction else iv1(id)=nint(v1(id)/q_step(id))+1 endif enddo ! else ! v1=matmul(k_b_m1,v1) iv1=nint(v1) ! if (.not.v_is_zero(v1-real(iv1,SP),zero_=local_zero)) then !$omp critical connected_grids=.false. !$omp end critical cycle endif ! call k_grid_shift(iv1) ! endif ! iqbz=q_map(iv1(1),iv1(2),iv1(3)) ! if (iks==1) qindx_S(ikibz,iqbz,1)=ikbz_p if (coll_scattering) qindx_C(ikbz,iqbz,1)=ikbz_p if (trim(convention)=="minus_q") v1=k%ptbz(ikbz,:)-k%ptbz(ikbz_p,:)-q%ptbz(iqbz,:) if (trim(convention)=="plus_q" ) v1=k%ptbz(ikbz_p,:)-k%ptbz(ikbz,:)-q%ptbz(iqbz,:) call c2a(v_in=v1,mode='ka2i') if (iks==1) qindx_S(ikibz,iqbz,2)=G_index(v1,.false.) if (coll_scattering) qindx_C(ikbz,iqbz,2)=G_index(v1,.false.) enddo ! if (master_thread) call live_timing(steps=1) ! enddo !$omp end do !$omp end parallel ! call live_timing() ! ! ... PARALLEL redux ! call live_timing(trim(string(2))//'[REDUX]',nqbz) do iqbz=1,nqbz call PP_redux_wait(qindx_S(:,iqbz,1)) call PP_redux_wait(qindx_S(:,iqbz,2)) if (coll_scattering) then call PP_redux_wait(qindx_C(:,iqbz,1)) call PP_redux_wait(qindx_C(:,iqbz,2)) endif call live_timing(steps=1) enddo call live_timing( ) ! if (.not.connected_grids) call msg('rsn','[RL indx] X & Total k-grids are not connected') ! K_LOOP: do ikbz=1,k%nbz ikibz=k%sstar(ikbz,1) if (any(qindx_S(ikibz,:,:)==0)) then call bz_X_only_exit('Null transition detected [qindx_S]. Gamma point only.') exit K_LOOP endif enddo K_LOOP ! qindx_S_max_Go=maxval(qindx_S(:,:,2)) ! endif ! ! Grids string update ! call k_GRIDS_update( ) ! ! Before writing the new DB I need to wait that all cores are done ! with checking DB which was present before ! call PP_wait() ! if(l_setup.and.fat_log) call print_q_indirect( ) ! if(master_cpu) then call io_control(ACTION=OP_WR_CL,COM=REP,SEC=(/1,2,3,4,6/),ID=io_db) io_err=io_QINDX(Xk,q,io_db,trim(convention)) endif ! ! Before writing section 5 (qindx_B) I need to wait that the master is done ! with writing all other sections ! call PP_wait() ! do_qindx_B=master_cpu.and.X_scattering.and.Xk_grid_is_uniform.and.bse_scattering #if defined _PAR_IO do_qindx_B=X_scattering.and.Xk_grid_is_uniform.and.bse_scattering #endif ! if (do_qindx_B) then call io_control(ACTION=OP_APP_CL,COM=REP,SEC=(/5/),ID=io_db,& & COMM=PAR_K_scheme%COM_ibz_index,DO_it=PAR_K_scheme%COM_ibz_A2A%CPU_id==0) io_err=io_QINDX(Xk,q,io_db,trim(convention)) endif ! !CLEAN ! call k_ibz2bz(Xk,'d',.false.) YAMBO_FREE(q_map) YAMBO_FREE(q_iptbz) if (Xk_grid_is_uniform) then YAMBO_FREE(q%ptbz) endif call qindx_free('B') call PP_wait() call PP_indexes_reset(PAR_IND_Xk) call PP_indexes_reset(PAR_IND_k) ! #if defined _PAR_IO if(X_scattering.and.Xk_grid_is_uniform.and.bse_scattering) call PARALLEL_global_indexes(en,Xk,q," ",RESET=.TRUE.) #endif ! call timing('bz_samp_indexes',OPR='stop') ! contains ! subroutine k_GRIDS_update() ! ! Grids string update ! k_GRIDS_string="" if (X_scattering ) k_GRIDS_string=trim(k_GRIDS_string)//" X" if (bse_scattering ) k_GRIDS_string=trim(k_GRIDS_string)//" B" if (coll_scattering ) k_GRIDS_string=trim(k_GRIDS_string)//" C" if (sigma_scattering) k_GRIDS_string=trim(k_GRIDS_string)//" S" if (trim(convention)=="plus_q" ) k_GRIDS_string=trim(k_GRIDS_string)//" plus_q" if (trim(convention)=="minus_q") k_GRIDS_string=trim(k_GRIDS_string)//" minus_q" ! if (len_trim(k_GRIDS_string)==0) k_GRIDS_string="none" ! ! This is needed for I/O ! k_GRIDS_vector=0 if (X_scattering ) k_GRIDS_vector(1)=1 if (bse_scattering ) k_GRIDS_vector(2)=1 if (coll_scattering ) k_GRIDS_vector(3)=1 if (sigma_scattering) k_GRIDS_vector(4)=1 ! end subroutine ! subroutine k_grid_shift(v) implicit none integer :: v(3),u(3),i1 do i1=1,3 if (v(i1)>=0) u(i1)=mod(v(i1)+1,k_grid(i1)) if (v(i1)>=0.and.u(i1)==0) u(i1)=k_grid(i1) if (v(i1)<0) u(i1)=mod(v(i1),k_grid(i1)) if (v(i1)<0.and.u(i1)/=0) u(i1)=u(i1)+k_grid(i1)+1 if (v(i1)<0.and.u(i1)==0) u(i1)=1 enddo v=u end subroutine ! subroutine define_q_map(qpt_map,q_ref) ! implicit none ! real(SP)::qpt_map(Xk%nbz,3),q_ref(3) ! q_map=0 do i1=1,Xk%nbz v1=matmul(k_b_m1,qpt_map(i1,:)-q_ref) q_iptbz(i1,:)=nint(v1) call k_grid_shift(q_iptbz(i1,:)) if (q_map(q_iptbz(i1,1),q_iptbz(i1,2),q_iptbz(i1,3))/=0) then call warning('[RL indx] 2 equivalent points in the rlu grid found') q_map=0 return endif q_map(q_iptbz(i1,1),q_iptbz(i1,2),q_iptbz(i1,3))=i1 enddo ! ! Now I fill the holes in the map shifting the whole grid ! do i1=1,Xk%nbz do i2=-2,2 do i3=-2,2 do i4=-2,2 v1=matmul(k_b_m1,qpt_map(i1,:)-q_ref+real((/i2,i3,i4/))) iv1=nint(v1) call k_grid_shift(iv1) if (q_map(iv1(1),iv1(2),iv1(3))==0) q_map(iv1(1),iv1(2),iv1(3))=i1 enddo enddo enddo enddo end subroutine ! subroutine define_q_map_new(qpt_map,q_ref) ! use pars, ONLY:zero_dfl ! implicit none ! real(SP) :: qpt_map(Xk%nbz,3) real(SP), intent(in) :: q_ref(3) ! ! Work space ! real(SP) :: qpt_save(Xk%nbz,3),q_step(3) integer :: id ! qpt_save=qpt_map ! ! Remove shift if present do id=1,3 qpt_map(:,id)=qpt_map(:,id)-q_ref(id) enddo ! qpt_map(:,:)=qpt_map(:,:)-nint(qpt_map(:,:)) ! Bring in the BZ ! ! Bring k-points between [0,1) ! where(qpt_map(:,:)<-zero_dfl) qpt_map(:,:)=1._SP+qpt_map(:,:) end where ! ! Find the smallest q in the 3 direction ! call k_find_smallest_q(qpt_map,q_step,Xk%nbz) ! q_map=0 do i1=1,Xk%nbz ! do id=1,3 ! if(q_step(id)==0._SP) then ! Non periodic directions q_iptbz(i1,id)=1 cycle endif ! q_iptbz(i1,id)=nint(qpt_map(i1,id)/q_step(id))+1 ! enddo ! q_map(q_iptbz(i1,1),q_iptbz(i1,2),q_iptbz(i1,3))=i1 ! enddo ! qpt_map=qpt_save ! if(any(q_map==0)) then call error('[RL indx] error in mapping') q_map=0 return endif ! end subroutine ! subroutine q_shadows(force_gamma_only) use vec_operate, ONLY:iku_v_norm logical ::force_gamma_only ! ! Gamma only, deallocate and reallocate ! using Gamma point only definition ! if (force_gamma_only) then YAMBO_FREE(k_pt) YAMBO_FREE(q_pt) YAMBO_FREE(q_norm) YAMBO_FREE(q_sstar) YAMBO_FREE(q%pt) nqbz=1 nqibz=1 q%nibz=1 q%nbz=1 endif ! if (.not.allocated(q_pt)) then YAMBO_ALLOC(q_pt,(q%nibz,3)) endif if (.not.allocated(k_pt)) then YAMBO_ALLOC(k_pt,(k%nibz,3)) endif if (.not.allocated(q_norm)) then YAMBO_ALLOC(q_norm,(q%nibz)) endif if (allocated(q%sstar).and..not.allocated(q_sstar)) then YAMBO_ALLOC(q_sstar,(q%nbz,2)) endif ! if (force_gamma_only) then YAMBO_ALLOC(q%pt,(q%nibz,3)) if (.not.allocated(q_sstar)) then YAMBO_ALLOC(q_sstar,(q%nbz,2)) endif q%pt=0._SP q_pt=0._SP k_pt=k%pt if(allocated(q_sstar)) q_sstar=1 q_norm=q0_def_norm smallest_q_norm=q0_def_norm else q_pt=q%pt k_pt=k%pt q_sstar=q%sstar q_norm(1)=q0_def_norm do i1=2,q%nibz q_norm(i1)=iku_v_norm(q_pt(i1,:)) enddo smallest_q_norm=minval(q_norm(2:)) endif ! end subroutine q_shadows ! subroutine bz_X_only_exit(message) character(*), intent(in) :: message call qindx_free('ALL') nqibz=1 if (X_scattering) then call qindx_alloc('X') do i1=1,Xk%nbz qindx_X(1,i1,1)=i1 qindx_X(1,i1,2)=1 enddo endif call msg('nsrn',trim(message)) call q_shadows(.true.) Xk_grid_is_uniform=.false. bse_scattering=.false. sigma_scattering=.false. coll_scattering=.false. end subroutine bz_X_only_exit ! subroutine print_q_indirect( ) ! use stderr, ONLY:intc use interfaces, ONLY:OCCUPATIONS_Gaps use com, ONLY:COMPOSE_spin_msg ! integer :: E_k_ind(n_sp_pol,2) integer :: okbz,ik,iqbz,i_sp_pol logical :: q_found ! call OCCUPATIONS_Gaps(en,E_k_ind=E_k_ind) ! if(all(E_k_ind(:,1)==E_k_ind(:,2))) return ! Direct gap case if(.not.allocated(qindx_S)) return ! do i_sp_pol=1,n_sp_pol q_found=.false. do iqbz=1,q%nbz okbz=qindx_S(E_k_ind(i_sp_pol,1),iqbz,1) if(k%sstar(okbz,1)==E_k_ind(i_sp_pol,2)) then q_found=.true. exit endif enddo if(q_found) call msg('r',COMPOSE_spin_msg('',0,'Q-point that connects indirect gap',i_sp_pol),q%sstar(iqbz,1)) enddo ! end subroutine print_q_indirect ! end subroutine