LCOV - code coverage report
Current view: top level - types - types_mpdata.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 221 250 88.4 %
Date: 2024-04-27 04:44:07 Functions: 14 18 77.8 %

          Line data    Source code
       1             : module m_types_mpdata
       2             :    implicit none
       3             : 
       4             :    type t_mpdata
       5             :       integer, allocatable   :: g(:, :) ! (3, num_gpts)
       6             :       integer, allocatable   :: n_g(:) ! (ik)
       7             :       integer, allocatable   :: gptm_ptr(:, :) ! (ig, ik)
       8             :       integer, allocatable   :: num_radbasfn(:, :) !(l,itype)
       9             :       real, allocatable      :: radbasfn_mt(:, :, :, :) !(jri,n,l,itype)
      10             :       INTEGER, ALLOCATABLE   :: num_radfun_per_l(:, :) !(l,itype)
      11             :       INTEGER                :: max_indx_p_1 = -1
      12             : 
      13             :       integer, allocatable   :: l1(:, :, :) !(n, l, itype)
      14             :       integer, allocatable   :: l2(:, :, :) !(n, l, itype)
      15             :       integer, allocatable   :: n1(:, :, :) !(n, l, itype)
      16             :       integer, allocatable   :: n2(:, :, :) !(n, l, itype)
      17             :    CONTAINS
      18             :       procedure :: num_gpts => mpdata_num_gpts
      19             :       procedure :: gen_gvec => mpdata_gen_gvec
      20             :       procedure :: check_orthonormality => mpdata_check_orthonormality
      21             :       procedure :: check_radbasfn => mpdata_check_radbasfn
      22             :       procedure :: calc_olap_radbasfn => mpdata_calc_olap_radbasfn
      23             :       procedure :: filter_radbasfn => mpdata_filter_radbasfn
      24             :       procedure :: trafo_to_orthonorm_bas => mpdata_trafo_to_orthonorm_bas
      25             :       procedure :: add_l0_fun => mpdata_add_l0_fun
      26             :       procedure :: reduce_linear_dep => mpdata_reduce_linear_dep
      27             :       procedure :: normalize => mpdata_normalize
      28             :       procedure :: set_nl => mpdata_set_nl
      29             :       procedure :: free => mpdata_free
      30             :       procedure :: init => mpdata_init
      31             :       procedure :: set_num_radfun_per_l => set_num_radfun_per_l_mpdata
      32             :       procedure :: set_max_indx_p_1 => set_max_indx_p_1
      33             :       !generic   :: write(unformatted) => write_mpdata
      34             :    end type t_mpdata
      35             : contains
      36          30 :    function mpdata_num_gpts(mpdata)
      37             :       implicit NONE
      38             :       class(t_mpdata), intent(in) :: mpdata
      39             :       integer    :: mpdata_num_gpts
      40             : 
      41          30 :       mpdata_num_gpts = size(mpdata%g, dim=2)
      42          30 :    end function mpdata_num_gpts
      43             : 
      44          12 :    subroutine mpdata_gen_gvec(mpdata, mpinp, cell, kpts, mpi)
      45             :       use m_judft
      46             :       use m_types_setup
      47             :       use m_types_kpts
      48             :       use m_types_mpi
      49             :       use m_types_mpinp
      50             :       USE m_constants
      51             :       use m_intgrf, only: intgrf_init, intgrf
      52             :       use m_sort
      53             :       implicit NONE
      54             :       class(t_mpdata), intent(inout) :: mpdata
      55             :       type(t_mpinp), intent(in)      :: mpinp
      56             :       type(t_cell), intent(in)       :: cell
      57             :       type(t_kpts), intent(in)       :: kpts
      58             :       type(t_mpi), intent(in)        :: mpi
      59             : 
      60             :       integer :: i, n, n1, n2, divconq
      61             :       integer :: x, y, z, ikpt, igpt
      62             :       integer :: g(3)
      63             :       real    :: longest_k, kvec(3)
      64             :       logical :: l_found_new_gpt, l_found_kg_in_sphere
      65             : 
      66          12 :       integer, allocatable            ::  unsrt_pgptm(:, :) ! unsorted pointers to g vectors
      67          12 :       real, allocatable               ::  length_kg(:, :) ! length of the vectors k + G
      68          12 :       integer, allocatable            ::  ptr(:)
      69             : 
      70          36 :       allocate(mpdata%n_g(kpts%nkptf))
      71             : 
      72         108 :       mpdata%n_g = 0
      73          12 :       i = 0
      74          12 :       n = -1
      75             : 
      76         492 :       longest_k = MAXVAL([(norm2(MATMUL(kpts%bkf(:, ikpt), cell%bmat)), ikpt=1, kpts%nkptf)])
      77             : 
      78             :       ! a first run for the determination of the dimensions of the fields g,pgptm
      79             : 
      80             :       do
      81         128 :          n = n + 1
      82         128 :          l_found_new_gpt = .FALSE.
      83        1576 :          do x = -n, n
      84        1448 :             n1 = n - ABS(x)
      85       13000 :             do y = -n1, n1
      86       11424 :                n2 = n1 - ABS(y)
      87       33068 :                do z = -n2, n2, MAX(2*n2, 1)
      88       80784 :                   g = [x, y, z]
      89      383724 :                   if((norm2(MATMUL(g, cell%bmat)) - longest_k) > mpinp%g_cutoff) CYCLE
      90        3092 :                   l_found_kg_in_sphere = .FALSE.
      91       39252 :                   do ikpt = 1, kpts%nkptf
      92      497812 :                      if(norm2(MATMUL(kpts%bkf(:, ikpt) + g, cell%bmat)) <= mpinp%g_cutoff) THEN
      93       13244 :                         if(.NOT. l_found_kg_in_sphere) THEN
      94        2368 :                            i = i + 1
      95        2368 :                            l_found_kg_in_sphere = .TRUE.
      96             :                         END if
      97             : 
      98       13244 :                         mpdata%n_g(ikpt) = mpdata%n_g(ikpt) + 1
      99       13244 :                         l_found_new_gpt = .TRUE.
     100             :                      END if
     101             :                   enddo ! k-loop
     102             :                enddo
     103             :             enddo
     104             :          enddo
     105         128 :          if(.NOT. l_found_new_gpt) EXIT
     106             :       enddo
     107             : 
     108          36 :       allocate(mpdata%g(3, i)) ! i = gptmd
     109         144 :       allocate(mpdata%gptm_ptr(maxval(mpdata%n_g), kpts%nkptf))
     110             : 
     111             :       ! allocate and initialize arrays needed for G vector ordering
     112         144 :       allocate(unsrt_pgptm(maxval(mpdata%n_g), kpts%nkptf))
     113         144 :       allocate(length_kG(maxval(mpdata%n_g), kpts%nkptf))
     114             : 
     115        9484 :       mpdata%g = 0
     116       14380 :       mpdata%gptm_ptr = 0
     117         108 :       mpdata%n_g = 0
     118             : 
     119         108 :       i = 0
     120         108 :       n = -1
     121             : 
     122       14380 :       length_kG = 0
     123       14380 :       unsrt_pgptm = 0
     124             : 
     125             :       do
     126         128 :          n = n + 1
     127         128 :          l_found_new_gpt = .FALSE.
     128        1576 :          do x = -n, n
     129        1448 :             n1 = n - ABS(x)
     130       13000 :             do y = -n1, n1
     131       11424 :                n2 = n1 - ABS(y)
     132       33068 :                do z = -n2, n2, MAX(2*n2, 1)
     133       80784 :                   g = [x, y, z]
     134      383724 :                   if((norm2(MATMUL(g, cell%bmat)) - longest_k) > mpinp%g_cutoff) CYCLE
     135        3092 :                   l_found_kg_in_sphere = .FALSE.
     136       39252 :                   do ikpt = 1, kpts%nkptf
     137       98944 :                      kvec = kpts%bkf(:, ikpt)
     138             : 
     139      473076 :                      if(norm2(MATMUL(kvec + g, cell%bmat)) <= mpinp%g_cutoff) THEN
     140       13244 :                         if(.NOT. l_found_kg_in_sphere) THEN
     141        2368 :                            i = i + 1
     142        9472 :                            mpdata%g(:, i) = g
     143             :                            l_found_kg_in_sphere = .TRUE.
     144             :                         END if
     145             : 
     146       13244 :                         mpdata%n_g(ikpt) = mpdata%n_g(ikpt) + 1
     147       13244 :                         l_found_new_gpt = .TRUE.
     148             : 
     149             :                         ! Position of the vector is saved as pointer
     150       13244 :                         unsrt_pgptm(mpdata%n_g(ikpt), ikpt) = i
     151             :                         ! Save length of vector k + G for array sorting
     152      251636 :                         length_kG(mpdata%n_g(ikpt), ikpt) = norm2(MATMUL(kvec + g, cell%bmat))
     153             :                      END if
     154             :                   enddo
     155             :                enddo
     156             :             enddo
     157             :          enddo
     158         128 :          if(.NOT. l_found_new_gpt) EXIT
     159             :       enddo
     160             : 
     161             :       ! Sort pointers in array, so that shortest |k+G| comes first
     162         108 :       do ikpt = 1, kpts%nkptf
     163         288 :          allocate(ptr(mpdata%n_g(ikpt)))
     164             :          ! create pointers which correspond to a sorted array (make algo stable)
     165       26680 :          call sort(ptr, length_kG(1:mpdata%n_g(ikpt), ikpt), [(1.0*i, i=1,mpdata%n_g(ikpt))])
     166             :          ! rearrange old pointers
     167       13340 :          do igpt = 1, mpdata%n_g(ikpt)
     168       13340 :             mpdata%gptm_ptr(igpt, ikpt) = unsrt_pgptm(ptr(igpt), ikpt)
     169             :          enddo
     170         108 :          deallocate(ptr)
     171             :       enddo
     172             : 
     173          12 :       if(mpi%irank == 0) THEN
     174           6 :          WRITE(oUnit, '(/A)') 'Mixed basis'
     175           6 :          WRITE(oUnit, '(A,I5)') 'Number of unique G-vectors: ', mpdata%num_gpts()
     176           6 :          WRITE(oUnit, *)
     177           6 :          WRITE(oUnit, '(3x,A)') 'IR Plane-wave basis with cutoff of gcutm (mpinp%g_cutoff/2*input%rkmax):'
     178          54 :          WRITE(oUnit, '(5x,A,I5)') 'Maximal number of G-vectors:', maxval(mpdata%n_g)
     179             :       END if
     180          12 :    end subroutine mpdata_gen_gvec
     181             : 
     182         200 :    subroutine mpdata_check_orthonormality(mpdata, atoms, mpi, l, itype, gridf)
     183             : 
     184             :       use m_judft
     185             :       use m_types_setup
     186             :       use m_types_mpi
     187             :       USE m_constants
     188             :       use m_intgrf, only: intgrf
     189             : 
     190             :       implicit none
     191             : 
     192             :       class(t_mpdata)          :: mpdata
     193             :       type(t_atoms), intent(in) :: atoms
     194             :       type(t_mpi), intent(in)   :: mpi
     195             :       integer, intent(in)       :: itype, l
     196             :       real, intent(in)          :: gridf(:, :)
     197             : 
     198         200 :       real, allocatable :: olap(:, :)
     199             :       integer           :: i, n_radbasfn, err_loc(2)
     200             : 
     201             :       CHARACTER, PARAMETER :: lchar(0:38) = ['s', 'p', 'd', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', &
     202             :                                              'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', &
     203             :                                              'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x']
     204             : 
     205         200 :       call timestart("check mpdata orthonormality")
     206             : 
     207             :       ! calculate overlap matrix
     208         200 :       call mpdata%calc_olap_radbasfn(atoms, l, itype, gridf, olap)
     209             : 
     210             :       !subtract identity-matrix
     211        1720 :       do i = 1, size(olap, dim=1)
     212        1720 :          olap(i, i) = olap(i, i) - 1.0
     213             :       enddo
     214             : 
     215             :       ! check if (olap - identity) is zero-matrix
     216       13608 :       if(norm2(olap) > 1e-6) then
     217           0 :          if(mpi%irank == 0) THEN
     218           0 :             err_loc = maxloc(abs(olap))
     219             :             WRITE(*, *) 'mixedbasis: Bad orthonormality of ' &
     220           0 :                //lchar(l)//'-mixet product basis. Increase tolerance.'
     221           0 :             write(*, *) "itype =", itype, "l =", l
     222           0 :             WRITE(*, *) 'Deviation of', &
     223           0 :                maxval(abs(olap)), ' occurred for (', &
     224           0 :                err_loc(1), ',', err_loc(2), ')-overlap.'
     225             :          endif
     226             :          CALL judft_error("Bad orthonormality of mpdata", &
     227             :                           hint='Increase tolerance', &
     228           0 :                           calledby='mixedbasis%check_orthonormality')
     229             :       endif
     230             : 
     231         200 :       if(mpi%irank == 0) THEN
     232         100 :          n_radbasfn = mpdata%num_radbasfn(l, itype)
     233             :          WRITE(oUnit, '(6X,A,I4,''   ('',F22.18,'' )'')') &
     234        6804 :             lchar(l)//':', n_radbasfn, norm2(olap)/n_radbasfn
     235             :       END if
     236         200 :       call timestop("check mpdata orthonormality")
     237         200 :    end subroutine mpdata_check_orthonormality
     238             : 
     239          12 :    subroutine mpdata_check_radbasfn(mpdata, atoms, hybinp)
     240             :       use m_judft
     241             :       use m_types_hybinp
     242             :       use m_types_setup
     243             :       implicit none
     244             :       class(t_mpdata), intent(in) :: mpdata
     245             :       type(t_atoms), intent(in)    :: atoms
     246             :       type(t_hybinp), intent(in)   :: hybinp
     247             : 
     248             :       integer :: itype
     249             : 
     250          32 :       do itype = 1, atoms%ntype
     251         132 :          if(ANY(mpdata%num_radbasfn(0:hybinp%lcutm1(itype), itype) == 0)) THEN
     252           0 :             call judft_error('any mpdata%num_radbasfn eq 0', calledby='mixedbasis')
     253             :          endif
     254             :       enddo
     255          12 :    end subroutine mpdata_check_radbasfn
     256             : 
     257         300 :    SUBROUTINE mpdata_calc_olap_radbasfn(mpdata, atoms, l, itype, gridf, olap)
     258             :       USE ieee_arithmetic
     259             :       use m_intgrf, only: intgrf
     260             :       use m_types_setup
     261             :       use m_judft
     262             :       use m_types_fleurinput_base, only: REAL_NOT_INITALIZED
     263             : 
     264             :       implicit NONE
     265             :       class(t_mpdata), intent(in)       :: mpdata
     266             :       type(t_atoms), intent(in)          :: atoms
     267             :       integer, intent(in)                :: l, itype
     268             :       real, intent(in)                   :: gridf(:, :)
     269             :       real, intent(inout), allocatable   :: olap(:, :)
     270             : 
     271             :       integer  :: n1, n2, n_radbasfn
     272             : 
     273         300 :       call timestart("calc mpdata overlap")
     274             : 
     275         300 :       n_radbasfn = mpdata%num_radbasfn(l, itype)
     276         300 :       if(allocated(olap)) then
     277          88 :          if(any(shape(olap) /= n_radbasfn)) then
     278          88 :             deallocate(olap)
     279             :          endif
     280             :       endif
     281         300 :       if(.not. allocated(olap)) allocate(olap(n_radbasfn, n_radbasfn), &
     282       92960 :                                          source=REAL_NOT_INITALIZED)
     283             : 
     284        4316 :       do n2 = 1, n_radbasfn
     285       50196 :          do n1 = 1, n2
     286             :             olap(n1, n2) = intgrf(mpdata%radbasfn_mt(:, n1, l, itype)*mpdata%radbasfn_mt(:, n2, l, itype), &
     287    36131800 :                                   atoms, itype, gridf)
     288             :             if(ieee_is_nan(olap(n1, n2))) then
     289             :                write(*, *) "nan at", n1, n2
     290             :             endif
     291       49896 :             olap(n2, n1) = olap(n1, n2)
     292             :          END do
     293             :       END do
     294             :       if(any(ieee_is_nan(olap))) call juDFT_error("Mixed-product basis olap is nan")
     295         300 :       call timestop("calc mpdata overlap")
     296         300 :    end subroutine mpdata_calc_olap_radbasfn
     297             : 
     298         100 :    subroutine mpdata_filter_radbasfn(mpdata, mpinp, l, itype, n_radbasfn, eig, eigv)
     299             :       ! Get rid of linear dependencies (eigenvalue <= mpdata%linear_dep_tol)
     300         300 :       use m_judft
     301             :       use m_types_mpinp
     302             :       implicit none
     303             :       class(t_mpdata), intent(inout)        :: mpdata
     304             :       type(t_mpinp), intent(in)             :: mpinp
     305             :       integer, intent(in)                   :: l, itype, n_radbasfn
     306             :       real, intent(inout)                   :: eig(:), eigv(:, :)
     307             : 
     308             :       integer              :: num_radbasfn, i_bas
     309         100 :       integer, allocatable :: remaining_basfn(:)
     310             : 
     311         100 :       call timestart("filer mpdata")
     312        2796 :       allocate(remaining_basfn(n_radbasfn), source=1)
     313         100 :       num_radbasfn = 0
     314             : 
     315        2596 :       do i_bas = 1, mpdata%num_radbasfn(l, itype)
     316        2596 :          if(eig(i_bas) > mpinp%linear_dep_tol) THEN
     317         740 :             num_radbasfn = num_radbasfn + 1
     318         740 :             remaining_basfn(num_radbasfn) = i_bas
     319             :          END if
     320             :       END do
     321             : 
     322         100 :       mpdata%num_radbasfn(l, itype) = num_radbasfn
     323        5292 :       eig = eig(remaining_basfn)
     324      156904 :       eigv(:, :) = eigv(:, remaining_basfn)
     325         100 :       call timestop("filer mpdata")
     326         100 :    end subroutine mpdata_filter_radbasfn
     327             : 
     328         100 :    subroutine mpdata_diagonialize_olap(olap, eig_val, eig_vec)
     329             :       use m_judft
     330             :       use m_types_fleurinput_base, only: REAL_NOT_INITALIZED
     331             :       implicit NONE
     332             :       real, intent(in)  :: olap(:, :)
     333             :       real, allocatable :: eig_val(:), eig_vec(:, :)
     334             : 
     335             :       integer              :: n, size_iwork(1), info
     336             :       real                 :: size_work(1)
     337         100 :       integer, allocatable :: iwork(:)
     338         100 :       real, allocatable    :: work(:)
     339             : 
     340         100 :       call timestart("diagonalize overlap")
     341         100 :       if(size(olap, dim=1) /= size(olap, dim=2)) then
     342           0 :          call juDFT_error("only square matrices can be diagonalized")
     343             :       endif
     344             : 
     345         100 :       n = size(olap, dim=1)
     346             : 
     347         100 :       if(allocated(eig_val)) then
     348          88 :          if(size(eig_val) /= n) deallocate(eig_val)
     349             :       endif
     350         300 :       if(.not. allocated(eig_val)) allocate(eig_val(n))
     351        2596 :       eig_val = REAL_NOT_INITALIZED
     352             : 
     353       78552 :       eig_vec = olap
     354             :       ! get sizes of work arrays
     355             :       call dsyevd('V', 'U', n, eig_vec, n, eig_val, &
     356         100 :                   size_work, -1, size_iwork, -1, info)
     357         100 :       if(info /= 0) call juDFT_error("diagonalization for size failed")
     358             : 
     359         300 :       allocate(work(int(size_work(1))))
     360         300 :       allocate(iwork(size_iwork(1)))
     361             : 
     362             :       call dsyevd('V', 'U', n, eig_vec, n, eig_val, &
     363         100 :                   work, int(size_work(1)), iwork, size_iwork(1), info)
     364         100 :       if(info /= 0) call juDFT_error("diagonalization failed")
     365         100 :       call timestop("diagonalize overlap")
     366         100 :    end subroutine mpdata_diagonialize_olap
     367             : 
     368         100 :    subroutine mpdata_trafo_to_orthonorm_bas(mpdata, full_n_radbasfn, n_grid_pt, l, itype, eig, eigv)
     369             :       use m_judft
     370             :       implicit NONE
     371             :       class(t_mpdata), intent(inout)  :: mpdata
     372             :       integer, intent(in)              :: full_n_radbasfn, n_grid_pt, l, itype
     373             :       real, intent(in)                 :: eig(:), eigv(:, :)
     374             : 
     375             :       integer :: nn, i
     376             : 
     377         100 :       call timestart("transform to reduced mpdata")
     378             :       ! reduced number of basis functions
     379         100 :       nn = mpdata%num_radbasfn(l, itype)
     380             : 
     381       80000 :       do i = 1, n_grid_pt
     382             :          mpdata%radbasfn_mt(i, 1:nn, l, itype) &
     383    16906296 :             = MATMUL(mpdata%radbasfn_mt(i, 1:full_n_radbasfn, l, itype), eigv(:, 1:nn))/SQRT(eig(:nn))
     384             :       END do
     385         100 :       call timestop("transform to reduced mpdata")
     386         100 :    end subroutine mpdata_trafo_to_orthonorm_bas
     387             : 
     388          20 :    subroutine mpdata_add_l0_fun(mpdata, atoms, hybinp, n_grid_pt, l, itype, gridf)
     389             :       use m_types_setup
     390             :       use m_types_hybinp
     391             :       use m_intgrf, only: intgrf
     392             :       use m_judft
     393             :       implicit none
     394             :       class(t_mpdata), intent(inout) :: mpdata
     395             :       type(t_atoms), intent(in)       :: atoms
     396             :       type(t_hybinp), intent(in)      :: hybinp
     397             :       integer, intent(in)             :: n_grid_pt, l, itype
     398             :       real, intent(in)                :: gridf(:, :)
     399             : 
     400             :       integer                         :: i, j, nn
     401          20 :       real, allocatable               :: basmhlp(:, :, :, :)
     402             :       real                            :: norm
     403             : 
     404          20 :       call timestart("add l0 to mpdata")
     405          20 :       nn = mpdata%num_radbasfn(l, itype)
     406          20 :       if(l == 0) THEN
     407             : 
     408             :          ! Check if radbasfn_mt must be reallocated
     409          20 :          if(nn + 1 > SIZE(mpdata%radbasfn_mt, 2)) THEN
     410           0 :             allocate(basmhlp(atoms%jmtd, nn + 1, 0:maxval(hybinp%lcutm1), atoms%ntype))
     411           0 :             basmhlp(:, 1:nn, :, :) = mpdata%radbasfn_mt
     412           0 :             deallocate(mpdata%radbasfn_mt)
     413           0 :             allocate(mpdata%radbasfn_mt(atoms%jmtd, nn + 1, 0:maxval(hybinp%lcutm1), atoms%ntype))
     414           0 :             mpdata%radbasfn_mt(:, 1:nn, :, :) = basmhlp(:, 1:nn, :, :)
     415           0 :             deallocate(basmhlp)
     416             :          END if
     417             : 
     418             :          ! add l = 0 function
     419             :          mpdata%radbasfn_mt(:n_grid_pt, nn + 1, 0, itype) &
     420       16000 :             = atoms%rmsh(:n_grid_pt, itype)/SQRT(atoms%rmsh(n_grid_pt, itype)**3/3)
     421             : 
     422             :          ! perform gram-schmidt orthonormalization
     423         180 :          do i = nn, 1, -1
     424         884 :             do j = i + 1, nn + 1
     425             :                mpdata%radbasfn_mt(:n_grid_pt, i, 0, itype) &
     426             :                   = mpdata%radbasfn_mt(:n_grid_pt, i, 0, itype) &
     427             :                     - intgrf( &
     428             :                     mpdata%radbasfn_mt(:n_grid_pt, i, 0, itype) &
     429             :                     *mpdata%radbasfn_mt(:n_grid_pt, j, 0, itype), &
     430             :                     atoms, itype, gridf) &
     431     1152128 :                     *mpdata%radbasfn_mt(:n_grid_pt, j, 0, itype)
     432             : 
     433             :             END do
     434             : 
     435             :             ! renormalize
     436      127784 :             norm = SQRT(intgrf(mpdata%radbasfn_mt(:n_grid_pt, i, 0, itype)**2, atoms, itype, gridf))
     437             :             mpdata%radbasfn_mt(:n_grid_pt, i, 0, itype) &
     438      127644 :                = mpdata%radbasfn_mt(:n_grid_pt, i, 0, itype)/norm
     439             :          END do
     440          20 :          nn = nn + 1
     441          20 :          mpdata%num_radbasfn(l, itype) = nn
     442             :       END if
     443          20 :       call timestop("add l0 to mpdata")
     444          20 :    end subroutine mpdata_add_l0_fun
     445             : 
     446          12 :    subroutine mpdata_reduce_linear_dep(mpdata, mpinp, atoms, mpi, hybinp, gridf, iterHF)
     447             :       use m_types_setup
     448             :       use m_types_hybinp
     449             :       use m_types_mpi
     450             :       use m_judft
     451             :       use m_types_mpinp
     452             :       implicit none
     453             :       class(t_mpdata)               :: mpdata
     454             :       type(t_mpinp), intent(in)     :: mpinp
     455             :       type(t_atoms), intent(in)     :: atoms
     456             :       type(t_mpi), intent(in)       :: mpi
     457             :       type(t_hybinp), intent(in)    :: hybinp
     458             :       integer, intent(in)           :: iterHF
     459             : 
     460          12 :       real, allocatable             :: olap(:, :), eig(:), eigv(:, :)
     461             :       real                          :: gridf(:, :)
     462             :       integer                       :: full_n_radbasfn, n_grid_pt, l, itype
     463             : 
     464             :       ! In order to get rid of the linear dependencies in the
     465             :       ! radial functions radbasfn_mt belonging to fixed l and itype
     466             :       ! the overlap matrix is diagonalized and those eigenvectors
     467             :       ! with a eigenvalue greater then mpdata%linear_dep_tol are retained
     468             : 
     469          12 :       call timestart("reduce lin. dep. mpdata")
     470             : 
     471          32 :       do itype = 1, atoms%ntype
     472          20 :          if (hybinp%lcutm1(itype) <= 0) call judft_error("lcutm1 <= 0 isn't allowed for hybrid calculations")
     473         132 :          DO l = 0, hybinp%lcutm1(itype)
     474         100 :             full_n_radbasfn = mpdata%num_radbasfn(l, itype)
     475         100 :             n_grid_pt = atoms%jri(itype)
     476             : 
     477             :             ! Calculate overlap
     478         100 :             call mpdata%calc_olap_radbasfn(atoms, l, itype, gridf, olap)
     479             : 
     480             :             ! Diagonalize
     481         100 :             call mpdata_diagonialize_olap(olap, eig, eigv)
     482             : 
     483         100 :             call mpdata%filter_radbasfn(mpinp, l, itype, full_n_radbasfn, eig, eigv)
     484             : 
     485         100 :             call mpdata%trafo_to_orthonorm_bas(full_n_radbasfn, n_grid_pt, l, itype, eig, eigv)
     486             : 
     487             :             ! Add constant function to l=0 basis and then do a Gram-Schmidt orthonormalization
     488         100 :             if(l == 0) then
     489          20 :                call mpdata%add_l0_fun(atoms, hybinp, n_grid_pt, l, itype, gridf)
     490             :             endif
     491             : 
     492             :             ! Check orthonormality of mpdatauct basis
     493         120 :             call mpdata%check_orthonormality(atoms, mpi, l, itype, gridf)
     494             :          enddo
     495             :       enddo
     496             : 
     497          12 :       deallocate(olap, eigv, eig)
     498          12 :       call timestop("reduce lin. dep. mpdata")
     499          12 :    end subroutine
     500             : 
     501          12 :    subroutine mpdata_normalize(mpdata, atoms, hybinp, gridf)
     502             :       use m_intgrf, only: intgrf
     503             :       use m_types_hybinp
     504             :       use m_types_setup
     505             :       use m_judft
     506             :       implicit NONE
     507             : 
     508             :       class(t_mpdata), intent(inout):: mpdata
     509             :       type(t_atoms), intent(in)      :: atoms
     510             :       type(t_hybinp), intent(in)     :: hybinp
     511             :       real, intent(in)               :: gridf(:, :)
     512             : 
     513             :       integer                        :: l, i_basfn, itype
     514             :       real                           :: norm
     515             : 
     516          32 :       do itype = 1, atoms%ntype
     517         132 :          do l = 0, hybinp%lcutm1(itype)
     518        2616 :             do i_basfn = 1, mpdata%num_radbasfn(l, itype)
     519             :                norm = SQRT( &
     520             :                       intgrf(mpdata%radbasfn_mt(:, i_basfn, l, itype)**2, &
     521             :                              atoms, itype, gridf) &
     522     1998176 :                       )
     523             :                mpdata%radbasfn_mt(:atoms%jri(itype), i_basfn, l, itype) &
     524     1969572 :                   = mpdata%radbasfn_mt(:atoms%jri(itype), i_basfn, l, itype)/norm
     525             :             end do
     526             :          end do
     527             :       end do
     528          12 :    end subroutine mpdata_normalize
     529             : 
     530          12 :    subroutine mpdata_init(mpdata, hybinp, hybdat, atoms)
     531             :       use m_types_setup
     532             :       use m_types_hybinp
     533             :       use m_types_hybdat
     534             :       use m_judft
     535             :       implicit none
     536             :       class(t_mpdata)           :: mpdata
     537             :       type(t_hybinp), intent(in) :: hybinp
     538             :       type(t_hybdat), intent(in) :: hybdat
     539             :       type(t_atoms), intent(in)  :: atoms
     540             : 
     541             :       integer                    :: ok
     542             : 
     543             : 
     544          12 :       call mpdata%set_max_indx_p_1(atoms, hybinp)
     545             : 
     546          12 :       if(.not. allocated(mpdata%l1)) then
     547             :          allocate(mpdata%l1(mpdata%max_indx_p_1, 0:maxval(hybinp%lcutm1), atoms%ntype),&
     548          40 :                   stat = ok)
     549           6 :          if(ok /= 0) call judft_error('mpdata_init: failure allocation mpdata%l1')
     550             : 
     551          30 :          allocate(mpdata%l2, mold=mpdata%l1, stat=ok)
     552           6 :          if(ok /= 0) call judft_error('mpdata_init: failure allocation mpdata%l2')
     553             : 
     554          30 :          allocate(mpdata%n1, mold=mpdata%l1, stat=ok)
     555           6 :          if(ok /= 0) call judft_error('mpdata_init: failure allocation mpdata%n1')
     556             : 
     557          30 :          allocate(mpdata%n2, mold=mpdata%l1, stat=ok)
     558           6 :          if(ok /= 0) call judft_error('mpdata_init: failure allocation mpdata%n2')
     559             : 
     560       50406 :          mpdata%l1 = -1; mpdata%l2 = -1; mpdata%n1 = -1; mpdata%n2 = -1
     561             :       endif
     562          12 :    end subroutine mpdata_init
     563             : 
     564          12 :    subroutine set_max_indx_p_1(mpdata, atoms, hybinp)
     565             :       use m_types_atoms
     566             :       use m_types_hybinp
     567             :       implicit none
     568             :       class(t_mpdata)             :: mpdata
     569             :       type(t_atoms), intent(in)   :: atoms
     570             :       type(t_hybinp), intent(in)  :: hybinp
     571             : 
     572             :       integer   :: itype, l, M, l1, l2, n1, n2
     573             : 
     574          12 :       mpdata%max_indx_p_1 = 0
     575             : 
     576          32 :       DO itype = 1, atoms%ntype
     577         132 :          DO l = 0, hybinp%lcutm1(itype)
     578         100 :             M = 0
     579        1080 :             DO l1 = 0, atoms%lmax(itype)
     580       10780 :                DO l2 = 0, atoms%lmax(itype)
     581       10680 :                   IF(l >= ABS(l1 - l2) .AND. l <= l1 + l2) THEN
     582       11396 :                      DO n1 = 1, mpdata%num_radfun_per_l(l1, itype)
     583       27468 :                         DO n2 = 1, mpdata%num_radfun_per_l(l2, itype)
     584       23768 :                            M = M + 1
     585             :                         END DO
     586             :                      END DO
     587             :                   END IF
     588             :                END DO
     589             :             END DO
     590         120 :             mpdata%max_indx_p_1 = MAX(mpdata%max_indx_p_1, M)
     591             :          END DO
     592             :       END DO
     593          12 :    end subroutine set_max_indx_p_1
     594             : 
     595           0 :    subroutine mpdata_free(mpdata)
     596             :       implicit NONE
     597             :       class(t_mpdata)          :: mpdata
     598             : 
     599           0 :       if(allocated(mpdata%l1)) deallocate(mpdata%l1)
     600           0 :       if(allocated(mpdata%l2)) deallocate(mpdata%l2)
     601           0 :       if(allocated(mpdata%n1)) deallocate(mpdata%n1)
     602           0 :       if(allocated(mpdata%n2)) deallocate(mpdata%n2)
     603           0 :    end subroutine mpdata_free
     604             : 
     605           0 :    subroutine mpdata_set_nl(mpdata, n, l, itype, n1, l1, n2, l2)
     606             :       implicit NONE
     607             :       class(t_mpdata)    :: mpdata
     608             :       integer, intent(in)  :: n, l, itype
     609             :       integer, intent(out) :: n1, l1, n2, l2
     610             : 
     611           0 :       l1 = mpdata%l1(n, l, itype) !
     612           0 :       l2 = mpdata%l2(n, l, itype) ! current basis-function mpdatauct
     613           0 :       n1 = mpdata%n1(n, l, itype) ! = bas(:,n1,l1,itype)*bas(:,n2,l2,itype) = b1*b2
     614           0 :       n2 = mpdata%n2(n, l, itype) !
     615             : 
     616           0 :    end subroutine mpdata_set_nl
     617             : 
     618          12 :    subroutine set_num_radfun_per_l_mpdata(mpdata, atoms)
     619             :       use m_types_setup
     620             :       implicit NONE
     621             :       class(t_mpdata) :: mpdata
     622             :       type(t_atoms)   :: atoms
     623             :       integer :: itype, ilo
     624             : 
     625          12 :       if(.not. allocated(mpdata%num_radfun_per_l)) then
     626           0 :          allocate(mpdata%num_radfun_per_l(0:atoms%lmaxd, atoms%ntype))
     627             :       endif
     628             : 
     629             :       ! always two there are: u and u_dot
     630         228 :       mpdata%num_radfun_per_l = 2
     631          32 :       DO itype = 1, atoms%ntype
     632          56 :          DO ilo = 1, atoms%nlo(itype)
     633             :             mpdata%num_radfun_per_l(atoms%llo(ilo, itype), itype) &
     634          44 :                = mpdata%num_radfun_per_l(atoms%llo(ilo, itype), itype) + 1
     635             :          END DO
     636             :       END DO
     637          12 :    end subroutine set_num_radfun_per_l_mpdata
     638       79900 : end module m_types_mpdata

Generated by: LCOV version 1.14