LCOV - code coverage report
Current view: top level - hybrid - calc_hybrid.F90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 103 106 97.2 %
Date: 2024-05-02 04:21:52 Functions: 2 2 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------
       2             : ! Copyright (c) 2016 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
       3             : ! This file is part of FLEUR and available as free software under the conditions
       4             : ! of the MIT license as expressed in the LICENSE file in more detail.
       5             : !--------------------------------------------------------------------------------
       6             : 
       7             : MODULE m_calc_hybrid
       8             :    USE m_judft
       9             :    use m_store_load_hybrid
      10             :    private
      11             :    public calc_hybrid
      12             : CONTAINS
      13             : 
      14         186 :    SUBROUTINE calc_hybrid(fi,mpdata,hybdat,fmpi,nococonv,stars,enpara,&
      15             :                           results,xcpot,v,iter, iterHF)
      16             :       use m_work_package
      17             :       use m_set_coul_participation
      18             :       USE m_types_hybdat
      19             :       USE m_types
      20             :       USE m_mixedbasis
      21             :       USE m_coulombmatrix
      22             :       USE m_hf_init
      23             :       USE m_hf_setup
      24             :       USE m_hsfock
      25             :       USE m_io_hybrid
      26             :       USE m_eig66_io
      27             :       use m_eig66_mpi
      28             :       use m_distribute_mpi 
      29             :       use m_create_coul_comms
      30             :       use m_eigvec_setup
      31             :       use m_distrib_vx
      32             :       use, intrinsic :: iso_c_binding
      33             : #ifdef CPP_MPI 
      34             :       use mpi 
      35             : #endif
      36             : #ifdef CPP_PROG_THREAD
      37             :       use m_thread_lib
      38             : #endif
      39             : 
      40             :       IMPLICIT NONE
      41             : 
      42             :       type(t_fleurinput), intent(in)    :: fi
      43             :       type(t_mpdata), intent(inout)     :: mpdata
      44             :       TYPE(t_hybdat), INTENT(INOUT)     :: hybdat
      45             :       TYPE(t_mpi), INTENT(IN)           :: fmpi
      46             :       TYPE(t_nococonv), INTENT(IN)      :: nococonv
      47             :       type(t_stars), intent(in)         :: stars
      48             :       TYPE(t_enpara), INTENT(IN)        :: enpara
      49             :       TYPE(t_results), INTENT(INOUT)    :: results
      50             :       TYPE(t_xcpot_inbuild), INTENT(IN) :: xcpot
      51             :       TYPE(t_potden), INTENT(IN)        :: v
      52             :       INTEGER, INTENT(INOUT)            :: iter, iterHF
      53             : 
      54             :       ! local variables
      55             :       type(t_hybmpi)           :: glob_mpi, wp_mpi
      56        1332 :       type(t_work_package)     :: work_pack(fi%input%jspins)
      57             :       INTEGER                  :: jsp, nk, err, i, wp_rank, ierr, ik
      58             :       INTEGER                  :: j_wp, n_wps, root_comm
      59             :       INTEGER                  :: max_band_pack, jq
      60         186 :       type(t_lapw)             :: lapw
      61             :       LOGICAL                  :: init_vex = .TRUE. !In first call we have to init v_nonlocal
      62             :       character(len=999)       :: msg
      63         186 :       REAL, ALLOCATABLE        :: eig_irr(:, :)
      64         186 :       integer, allocatable     :: vx_loc(:,:), weights(:)
      65             :       type(c_ptr)              :: threadId
      66         186 :       type(t_mat), allocatable :: vx_tmp(:,:)
      67             : 
      68         186 :       CALL timestart("hybrid code")
      69             : 
      70             : #ifdef CPP_MPI
      71             : #ifdef CPP_PROG_THREAD
      72         186 :       if(fmpi%l_mpi_multithreaded) call start_prog_thread(threadId)
      73             : #endif
      74             : #endif
      75             : 
      76         186 :       IF (fi%kpts%nkptf == 0) THEN
      77             :          CALL judft_error("kpoint-set of full BZ not available", &
      78           0 :                           hint="to generate fi%kpts in the full BZ you should specify a k-mesh in inp.xml")
      79             :       END IF
      80             : 
      81             :       !Check if new non-local potential shall be generated
      82         186 :       hybdat%l_subvxc = fi%hybinp%l_hybrid .AND. (.NOT. xcpot%is_name("exx"))
      83             :       !If this is the first iteration loop we can not calculate a new non-local potential
      84             :       !hybdat%l_calhf = (results%last_distance >= 0.0) .AND. (results%last_distance < fi%input%minDistance)
      85             :       !make sure we do at least one PBE first
      86         186 :       if(iter == 1 .and. iterHF == 0) hybdat%l_calhf = .False.
      87             : 
      88         186 :       IF (.NOT. hybdat%l_calhf) THEN
      89         262 :          hybdat%l_subvxc = hybdat%l_subvxc .AND. hybdat%l_addhf
      90             :       else
      91          12 :          call glob_mpi%init(fmpi%mpi_comm)
      92          12 :          results%te_hfex%core = 0
      93             : 
      94             :          !Check if we are converged well enough to calculate a new potential
      95          12 :          hybdat%l_addhf = .TRUE.
      96             : 
      97             :          !In first iteration allocate some memory
      98          12 :          IF (init_vex) THEN
      99           6 :             call first_iteration_alloc(fi, hybdat)
     100           6 :             init_vex = .FALSE.
     101             :          END IF
     102          12 :          hybdat%l_subvxc = (hybdat%l_subvxc .AND. hybdat%l_addhf)
     103          12 :          IF (.NOT. ALLOCATED(results%w_iks)) allocate(results%w_iks(fi%input%neig, fi%kpts%nkpt, fi%input%jspins))
     104             : 
     105          12 :          iterHF = iterHF + 1
     106             : 
     107             :          !Delete broyd files
     108          12 :          CALL system("rm -f broyd*")
     109             : 
     110             :          !check if z-reflection trick can be used
     111             : 
     112             :         
     113          12 :          CALL timestart("Preparation for hybrid functionals")
     114             :          !construct the mixed-basis
     115          12 :          CALL timestart("generation of mixed basis")
     116          12 :          if(glob_mpi%rank == 0) write (*,*) "iterHF =    " // int2str(iterHF)
     117             :          CALL mixedbasis(fi%atoms, fi%kpts,  fi%input, fi%cell, xcpot, fi%mpinp, mpdata, fi%hybinp, hybdat,&
     118          12 :                         enpara, fmpi, v, iterHF)
     119          12 :          CALL timestop("generation of mixed basis")
     120             : 
     121             :          ! setup parallelization 
     122          12 :          n_wps = min(glob_mpi%size, fi%kpts%nkpt)
     123          60 :          allocate(weights(n_wps), source=0)
     124          36 :          do j_wp = 1, n_wps
     125          36 :             do ik = j_wp, fi%kpts%nkpt, n_wps
     126          36 :                weights(j_wp) =  weights(j_wp) + fi%kpts%eibz(ik)%nkpt
     127             :             enddo
     128             :          enddo
     129          12 :          call distribute_mpi(weights, glob_mpi, wp_mpi, wp_rank)
     130          12 :          call hybdat%set_nobd(fi, results)
     131          12 :          call hybdat%set_nbands(fi, fmpi, results)
     132          28 :          do jsp = 1,fi%input%jspins
     133          28 :             call work_pack(jsp)%init(fi, hybdat, mpdata, wp_mpi, jsp, wp_rank, n_wps)
     134             :          enddo
     135             : 
     136         102 :          if(.not. allocated(hybdat%zmat)) allocate(hybdat%zmat(fi%kpts%nkptf, fi%input%jspins))
     137             : 
     138          28 :          DO jsp = 1, fi%input%jspins
     139         156 :             DO nk = 1,fi%kpts%nkptf
     140             : !               IF (hybdat%zmat(nk, jsp)%mat%matsize2 .NE. hybdat%nbands(nk, jsp)) THEN ! This IF caused deadlocks.
     141         128 :                   CALL lapw%init(fi%input, fi%noco, nococonv,fi%kpts, fi%atoms, fi%sym, nk, fi%cell)
     142             :                   call eigvec_setup(hybdat%zmat(nk, jsp), fi, lapw, work_pack, fmpi, &
     143         144 :                                     hybdat%nbands(nk, jsp), nk, jsp, hybdat%eig_id)
     144             : !               END IF
     145             :             enddo 
     146             :          enddo
     147          12 :          call bcast_eigvecs(hybdat, fi, nococonv, fmpi)
     148             : 
     149          42 :          if(.not. allocated(hybdat%coul)) allocate(hybdat%coul(fi%kpts%nkpt))
     150          12 :          call set_coul_participation(hybdat, fi, fmpi, work_pack)
     151          12 :          call create_coul_comms(hybdat, fi, fmpi)
     152             : 
     153          48 :          do i =1,fi%kpts%nkpt
     154          48 :             if(hybdat%coul(i)%l_participate) then 
     155          36 :                call hybdat%coul(i)%alloc(fi, mpdata%num_radbasfn, mpdata%n_g, i, .false.)
     156             :             else 
     157           0 :                call hybdat%coul(i)%mini_alloc(fi)
     158             :             endif 
     159             :          enddo 
     160             : 
     161             :          ! use jsp=1 for coulomb work-planning
     162          12 :          CALL coulombmatrix(fmpi, fi, mpdata, hybdat, xcpot)
     163             :          
     164          48 :          do i =1,fi%kpts%nkpt
     165          48 :             if(hybdat%coul(i)%l_participate) then 
     166          36 :                call hybdat%coul(i)%mpi_bcast(fi, hybdat%coul(i)%comm, 0)
     167             :             endif
     168             :          enddo
     169             : 
     170          12 :          CALL hf_init(mpdata, fi, hybdat)
     171          12 :          CALL timestop("Preparation for hybrid functionals")
     172             : 
     173          12 :          call judft_comm_split(glob_mpi%comm, wp_mpi%rank, 0, root_comm)
     174             : 
     175          12 :          CALL timestart("Calculation of non-local HF potential")
     176         112 :          allocate(vx_loc(fi%kpts%nkpt,fi%input%jspins), source=-1)
     177         112 :          allocate(vx_tmp(fi%kpts%nkpt, fi%input%jspins))
     178          28 :          DO jsp = 1, fi%input%jspins
     179             :             CALL HF_setup(mpdata,fi, fmpi, nococonv, results, jsp, enpara, &
     180          16 :                         hybdat, v%mt(:, 0, :, :), eig_irr)
     181             : 
     182          16 :             call timestart("get max_q")
     183          16 :             hybdat%max_q = 0
     184          40 :             DO i = 1,work_pack(jsp)%k_packs(1)%size
     185          24 :                max_band_pack = 0 
     186         112 :                DO jq = 1, size(work_pack(jsp)%k_packs(i)%q_packs)
     187         112 :                   max_band_pack = max(max_band_pack, work_pack(jsp)%k_packs(i)%q_packs(jq)%submpi%size)
     188             :                enddo
     189          40 :                hybdat%max_q = hybdat%max_q + size(work_pack(jsp)%k_packs(i)%q_packs) * fi%kpts%nkptf  * max_band_pack
     190             :             END DO
     191             : #ifdef CPP_MPI
     192          16 :             call MPI_Allreduce(MPI_IN_PLACE, hybdat%max_q, 1, MPI_INTEGER, MPI_MAX, MPI_COMM_WORLD, ierr)
     193             : #endif
     194          16 :             hybdat%max_q = hybdat%max_q + 20 ! The 20 is kind of dirty. It is meant as a safety because of the MPI_BARRIER in hsfock, related to the ex_to_vx call.
     195          16 :             call timestop("get max_q")
     196             : 
     197          40 :             DO i = 1,work_pack(jsp)%k_packs(1)%size
     198          24 :                nk = work_pack(jsp)%k_packs(i)%nk
     199          24 :                PRINT*, 'kpoint= ', nk
     200          24 :                CALL lapw%init(fi%input, fi%noco, nococonv,fi%kpts, fi%atoms, fi%sym, nk, fi%cell)
     201             :                CALL hsfock(fi, work_pack(jsp)%k_packs(i), mpdata, lapw, jsp, hybdat, eig_irr, &
     202          24 :                            nococonv, stars, results, xcpot, fmpi, vx_tmp(nk, jsp))
     203          40 :                if(work_pack(jsp)%k_packs(i)%submpi%root()) vx_loc(nk, jsp) = fmpi%irank
     204             :             END DO
     205             : 
     206             : #ifdef CPP_MPI
     207          16 :             CALL timestart("balancing MPI_Barriers")
     208        1056 :             DO WHILE (hybdat%max_q > 0)
     209        1040 :                call MPI_Barrier(MPI_COMM_WORLD, ierr)
     210        1040 :                hybdat%max_q = hybdat%max_q - 1
     211             :             END DO
     212          16 :             CALL timestop("balancing MPI_Barriers")
     213             : #endif
     214             : 
     215          28 :             call work_pack(jsp)%free()
     216             :          END DO
     217             : #ifdef CPP_MPI
     218          12 :          call timestart("MPI_Allred te_hfex%core")
     219          12 :          if(wp_mpi%rank == 0) call MPI_Allreduce(MPI_IN_PLACE, results%te_hfex%core, 1, MPI_DOUBLE_PRECISION, MPI_SUM, root_comm, ierr)
     220          12 :          call timestop("MPI_Allred te_hfex%core")
     221             : #endif
     222          12 :          CALL timestop("Calculation of non-local HF potential")
     223             : #ifdef CPP_MPI
     224          36 :          call MPI_Allreduce(MPI_IN_PLACE, vx_loc, size(vx_loc), MPI_INTEGER, MPI_MAX, fmpi%mpi_comm, ierr)   
     225             : #endif
     226          12 :          call distrib_vx(fi, fmpi, nococonv, vx_loc, vx_tmp, hybdat)
     227          12 :          call store_hybrid_data(fi, fmpi, hybdat)
     228             : 
     229             : #ifdef CPP_MPI
     230          12 :          call timestart("Hybrid imbalance")
     231             :          call MPI_Barrier(fmpi%mpi_comm, err)
     232          12 :          call timestop("Hybrid imbalance")
     233             : #endif
     234             : 
     235             :       ENDIF
     236             : 
     237             : #ifdef CPP_MPI
     238             : #ifdef CPP_PROG_THREAD
     239         186 :       if(fmpi%l_mpi_multithreaded) call stop_prog_thread(threadId)
     240             : #endif
     241             : #endif
     242         420 :       CALL timestop("hybrid code")
     243             :    CONTAINS
     244           6 :       subroutine first_iteration_alloc(fi, hybdat)
     245             :          implicit none
     246             :          type(t_fleurinput), intent(in)    :: fi
     247             :          TYPE(t_hybdat), INTENT(INOUT)     :: hybdat
     248             : 
     249           6 :          if(allocated(hybdat%nbands)) then
     250           0 :             deallocate(hybdat%nbands, stat=err, errmsg=msg)
     251             :             if(err /= 0) THEN
     252             :                write (*,*) "errorcode", err
     253             :                write (*,*) "errormessage", msg
     254             :             endif
     255             :          endif
     256             : 
     257          96 :          allocate(hybdat%nbands(fi%kpts%nkptf, fi%input%jspins), source=0)
     258             : 
     259           6 :          if(allocated(hybdat%nbasm)) deallocate(hybdat%nbasm)
     260          66 :          allocate(hybdat%nbasm(fi%kpts%nkptf), source=0)
     261             : 
     262           6 :          if(allocated(hybdat%div_vv)) deallocate(hybdat%div_vv)
     263        1682 :          allocate(hybdat%div_vv(fi%input%neig, fi%kpts%nkpt, fi%input%jspins), source=0.0)
     264           6 :       end subroutine first_iteration_alloc
     265             :    END SUBROUTINE calc_hybrid
     266             : END MODULE m_calc_hybrid

Generated by: LCOV version 1.14