LCOV - code coverage report
Current view: top level - src/56_recipspace - m_getshell.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.6 % 244 182
Test Date: 2026-11-06 01:31:13 Functions: 100.0 % 1 1
Branches: 73.6 % 246 181

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_getshell
       2                 :             : !! NAME
       3                 :             : !!  m_getshell
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 1999-2026 ABINIT group (MVeithen)
      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                 :             : module m_getshell
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_abicore
      26                 :             :  use m_xmpi
      27                 :             :  use m_errors
      28                 :             :  use m_linalg_interfaces
      29                 :             : 
      30                 :             :  use m_kpts,            only : getkgrid
      31                 :             : 
      32                 :             :  implicit none
      33                 :             : 
      34                 :             :  private
      35                 :             : !!***
      36                 :             : 
      37                 :             :  public :: getshell
      38                 :             : !!***
      39                 :             : 
      40                 :             : contains
      41                 :             : !!***
      42                 :             : 
      43                 :             : !!****f* ABINIT/getshell
      44                 :             : !! NAME
      45                 :             : !! getshell
      46                 :             : !!
      47                 :             : !! FUNCTION
      48                 :             : !! For each k-point, set up the shells of first neighbours and find
      49                 :             : !! the weigths required for the finite difference expression
      50                 :             : !! of Marzari and Vanderbilt (see PRB 56, 12847 (1997) [[cite:Marzari1997]]).
      51                 :             : !!
      52                 :             : !! INPUTS
      53                 :             : !! gmet(3,3) = metric tensor of reciprocal space
      54                 :             : !! kptopt = option for the generation of k points
      55                 :             : !! kptrlatt = k-point lattice specification
      56                 :             : !! kpt2(3,nkpt2) = reduced coordinates of the k-points in the
      57                 :             : !!                 reduced part of the BZ (see below)
      58                 :             : !! mkmem = number of k points which can fit in memory
      59                 :             : !! nkpt2 = number of k-points in the reduced BZ
      60                 :             : !! nkpt3 = number of k-points in the full BZ
      61                 :             : !! nshiftk = number of kpoint grid shifts
      62                 :             : !! rmet(3,3) = metric tensor of real space
      63                 :             : !! rprimd(3,3) = dimensional primitive translations (bohr)
      64                 :             : !! shiftk = shift vectors for k point generation
      65                 :             : !! wtk2 = weight assigned to each k point
      66                 :             : !! comm=MPI communicator
      67                 :             : !!
      68                 :             : !! OUTPUT
      69                 :             : !! kneigh(30,nkpt2) = for each k-point in the reduced part of the BZ
      70                 :             : !!                    kneigh stores the index (ikpt) of the neighbouring
      71                 :             : !!                    k-points
      72                 :             : !! kg_neigh(30,nkpt2,3) = kg-neigh takes values of -1, 0 or 1,
      73                 :             : !!                        and can be non-zero only for a single k-point,
      74                 :             : !!                        a line of k-points or a plane of k-points.
      75                 :             : !!                        The vector joining the ikpt2-th k-point to its
      76                 :             : !!                        ineigh-th nearest neighbour is :
      77                 :             : !!                        dk(:)-nint(dk(:))+real(kg_neigh(ineigh,ikpt2,:))
      78                 :             : !!                        with dk(:)=kpt2(:,kneigh(ineigh,ikpt2))-kpt2(:,ikpt2)
      79                 :             : !! kptindex(2,nkpt3)
      80                 :             : !!   kptindex(1,ikpt) = ikpt_rbz
      81                 :             : !!     ikpt_rbz = index of the k-point in the reduced BZ
      82                 :             : !!     ikpt = index of the k-point in the full BZ
      83                 :             : !!   kptindex(2,ikpt) = 1: use time-reversal symmetry to transform the
      84                 :             : !!                         wavefunction at ikpt_rbz to the wavefunction at ikpt
      85                 :             : !!                      0: ikpt belongs already to the reduced BZ
      86                 :             : !!                         (no transformation required)
      87                 :             : !! kpt3(3,nkpt3) = reduced coordinates of the k-points in the full BZ
      88                 :             : !! mvwtk(30,nkpt2) = weights required to evaluate the finite difference
      89                 :             : !!                   formula of Marzari and Vanderbilt, computed for each
      90                 :             : !!                   k-point in the reduced part of the BZ
      91                 :             : !! mkmem_max = maximal number of k-points on each processor (MPI //)
      92                 :             : !! nneigh = total number of neighbours required to evaluate the finite
      93                 :             : !!          difference formula
      94                 :             : !!
      95                 :             : !! COMMENTS
      96                 :             : !! The array kpt2 holds the reduced coordinates of the k-points in the
      97                 :             : !! reduced part of the BZ. For example, in case time-reversal symmetry is
      98                 :             : !! used (kptopt = 2) kpt2 samples half the BZ. Since some of the neighbours
      99                 :             : !! of these k-points may lie outside the reduced BZ, getshell also needs the
     100                 :             : !! coordinates of the k-points in the full BZ.
     101                 :             : !! The coordinates of the k-points in the full BZ are stored in kpt3.
     102                 :             : !! The weights mvwtk are computed for the k-points kpt2.
     103                 :             : !!
     104                 :             : !! In case no symmetry is used to reduce the number of k-points,
     105                 :             : !! the arrays kpt2 and kpt3 are equal.
     106                 :             : !!
     107                 :             : !! SOURCE
     108                 :             : 
     109                 :          21 : subroutine getshell(gmet,kneigh,kg_neigh,kptindex,kptopt,kptrlatt,kpt2,&
     110                 :          21 : & kpt3,mkmem,mkmem_max,mvwtk,&
     111                 :          21 : & nkpt2,nkpt3,nneigh,nshiftk,rmet,rprimd,shiftk,wtk2, comm)
     112                 :             : 
     113                 :             : !Arguments ------------------------------------
     114                 :             : !scalars
     115                 :             :  integer,intent(in) :: kptopt,mkmem,nkpt2,nkpt3,comm
     116                 :             :  integer,intent(inout) :: nshiftk
     117                 :             :  integer,intent(out) :: mkmem_max,nneigh
     118                 :             : !arrays
     119                 :             :  integer,intent(inout) :: kptrlatt(3,3)
     120                 :             :  integer,intent(out) :: kneigh(30,nkpt2),kptindex(2,nkpt3),kg_neigh(30,nkpt2,3)
     121                 :             :  real(dp),intent(in) :: gmet(3,3),kpt2(3,nkpt2),rmet(3,3),rprimd(3,3)
     122                 :             :  real(dp),intent(in) :: shiftk(3,nshiftk),wtk2(nkpt2)
     123                 :             :  real(dp),intent(out) :: kpt3(3,nkpt3),mvwtk(30,nkpt2)
     124                 :             : 
     125                 :             : !Local variables-------------------------------
     126                 :             : !scalars
     127                 :             :  integer :: bis,flag,ier,ii,ikpt,ikpt2,ikpt3,ineigh,info,irank,is1,ishell
     128                 :             :  integer :: jj,kptopt_used,mkmem_cp,nkpt_computed,nshell,nsym1,orig
     129                 :             :  integer :: wtkflg, coord1, coord2, coord3
     130                 :             :  real(dp) :: dist_,kptrlen,last_dist,max_dist,resdm,s1, max_err, my_tol
     131                 :             :  character(len=500) :: msg
     132                 :             : !arrays
     133                 :             :  integer :: unts(2)
     134                 :          42 :  integer :: neigh(0:6,nkpt2),symafm_dummy(1),vacuum(3)
     135                 :          21 :  integer,allocatable :: symrel1(:,:,:)
     136                 :             :  real(dp) :: dist(6),dk(3),dk_(3),mat(6,6),rvec(6),sgval(6)
     137                 :             :  real(dp) :: shiftk_(3,MAX_NSHIFTK),work(30)
     138                 :          21 :  real(dp),allocatable :: tnons1(:,:),wtk3(:)
     139                 :             : 
     140                 :             : !************************************************************************
     141                 :             : 
     142                 :             : !In case of MPI //: compute maximum number of k-points per processor
     143                 :             :  if (xmpi_paral == 1) then
     144                 :          21 :    mkmem_cp=mkmem
     145                 :          21 :    call xmpi_max(mkmem_cp,mkmem_max,comm,ier)
     146                 :             :  else
     147                 :             :    mkmem_max = mkmem
     148                 :             :  end if
     149                 :             : 
     150         [ +  + ]:          63 :  unts = [std_out, ab_out]
     151                 :             : 
     152                 :             : !------------- In case kptopt = 2 set up the whole k-point grid -------------
     153                 :             : 
     154                 :             : !kpt3(3,nkpt3) = reduced coordinates of k-points in the full BZ
     155                 :             : 
     156         [ -  + ]:          21 :  if (kptopt == 3) then
     157                 :             : 
     158   [ #  #  #  #  :           0 :    ABI_MALLOC(wtk3,(nkpt3))
          #  #  #  #  #  
                #  #  # ]
     159   [ #  #  #  # ]:           0 :    kpt3(:,:) = kpt2(:,:)
     160         [ #  # ]:           0 :    wtk3(:) = wtk2(:)
     161         [ #  # ]:           0 :    do ikpt = 1,nkpt3
     162                 :           0 :      kptindex(1,ikpt) = ikpt
     163                 :           0 :      kptindex(2,ikpt) = 0
     164                 :             :    end do
     165                 :             : 
     166         [ +  - ]:          21 :  else if (kptopt == 2) then
     167                 :             : 
     168   [ -  +  +  -  :          63 :    ABI_MALLOC(wtk3,(nkpt3))
          +  -  +  -  -  
                +  -  + ]
     169                 :          21 :    ii = 5 ; kptopt_used = 3
     170                 :          21 :    symafm_dummy(1) = 1
     171                 :          21 :    shiftk_(:,:) = 0._dp
     172   [ +  +  +  + ]:         105 :    shiftk_(:,1:nshiftk) = shiftk(:,1:nshiftk)
     173                 :             : 
     174                 :          21 :    nsym1 = 1
     175         [ -  + ]:          21 :    ABI_MALLOC(symrel1,(3,3,nsym1))
     176         [ -  + ]:          21 :    ABI_MALLOC(tnons1,(3,nsym1))
     177   [ +  +  +  + ]:         273 :    symrel1(:,:,1) = 0
     178                 :          21 :    symrel1(1,1,1) = 1 ; symrel1(2,2,1) = 1 ; symrel1(3,3,1) = 1
     179   [ +  +  +  + ]:         105 :    tnons1(:,:) = 0._dp
     180                 :          21 :    vacuum(:) = 0
     181                 :             : 
     182                 :             :    call getkgrid(0,0,ii,kpt3,kptopt_used,kptrlatt,&
     183                 :             :      kptrlen,nsym1,nkpt3,nkpt_computed,nshiftk,nsym1,&
     184                 :             :      rprimd,shiftk_,symafm_dummy,symrel1,&
     185                 :          21 :      vacuum,wtk3)
     186                 :             : 
     187         [ -  + ]:          21 :    if (nkpt_computed /= nkpt3) then
     188                 :             :      write(msg,'(a,a,a,a,i0,a,a,i0)')&
     189                 :           0 :       ' The number of k-points in the whole BZ, nkpt_computed= ',nkpt_computed,ch10,&
     190                 :           0 :       ' is not twice the number of k-points in half the BZ, nkpt3=',nkpt3
     191                 :           0 :      ABI_BUG(msg)
     192                 :             :    end if
     193                 :             : 
     194   [ +  +  +  + ]:        3966 :    kptindex(:,:) = 0
     195         [ +  + ]:        1336 :    do ikpt3 = 1, nkpt3
     196                 :             : 
     197                 :      190511 :      flag = 1
     198         [ +  - ]:      190511 :      do ikpt2 = 1, nkpt2
     199                 :             : 
     200                 :             : !      In case the k-points differ only by one reciprocal lattice
     201                 :             : !      vector, apply shift of one g-vector to kpt(:,ikpt3)
     202                 :             : !     MJV 10/2019: this appears to be using time reversal sym, instead of the G vector...
     203                 :             : !      could be equivalent to keep points inside the 1st BZ, but the code below is not consistent
     204                 :             : !      with this comment
     205                 :             : 
     206                 :             : !
     207                 :             : !  here k3 = k2 + G
     208                 :             : !
     209         [ +  + ]:      762044 :        dk_(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
     210         [ +  + ]:      762044 :        dk(:) = dk_(:) - nint(dk_(:))
     211         [ +  + ]:      190511 :        if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
     212         [ +  + ]:        2632 :          do ii = 1, 3
     213   [ +  -  -  + ]:        2632 :            if ((dk(ii)*dk(ii) < tol10).and.(dk_(ii)*dk_(ii) > tol10)) then
     214                 :             : !  transform k3 to -k3
     215                 :             : !  TODO: I suspect this should be k3 -= G!!
     216                 :           0 :              kpt3(ii,ikpt3) = -1._dp*kpt3(ii,ikpt3)
     217                 :             :            end if
     218                 :             :          end do
     219                 :             :        end if
     220                 :             : 
     221                 :             : !
     222                 :             : ! here k3 = -k2 + G
     223                 :             : !
     224         [ +  + ]:      762044 :        dk_(:) = kpt3(:,ikpt3) + kpt2(:,ikpt2)
     225         [ +  + ]:      762044 :        dk(:) = dk_(:) - nint(dk_(:))
     226         [ +  + ]:      190511 :        if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
     227         [ +  + ]:        2632 :          do ii = 1, 3
     228   [ +  -  +  + ]:        2632 :            if ((dk(ii)*dk(ii) < tol10).and.(dk_(ii)*dk_(ii) > tol10)) then
     229                 :             : !  transform k3 to -k3
     230                 :             : !  TODO: I suspect this should be k3 -= G!!
     231                 :         302 :              kpt3(ii,ikpt3) = -1._dp*kpt3(ii,ikpt3)
     232                 :             :            end if
     233                 :             :          end do
     234                 :             :        end if
     235                 :             : 
     236                 :             : 
     237                 :             : !
     238                 :             : ! here k3 = k2
     239                 :             : !
     240         [ +  + ]:      762044 :        dk(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
     241         [ +  + ]:      190511 :        if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
     242                 :         658 :          kptindex(1,ikpt3) = ikpt2
     243                 :         658 :          kptindex(2,ikpt3) = 0       ! no use of time-reversal symmetry
     244                 :             :          flag = 0
     245                 :             :          exit
     246                 :             :        end if
     247                 :             : 
     248                 :             : !
     249                 :             : ! here k3 = -k2
     250                 :             : !
     251         [ +  + ]:      759412 :        dk(:) = kpt3(:,ikpt3) + kpt2(:,ikpt2)
     252         [ +  + ]:      189853 :        if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
     253                 :         657 :          kptindex(1,ikpt3) = ikpt2
     254                 :         657 :          kptindex(2,ikpt3) = 1       ! use time-reversal symmetry
     255                 :             :          flag = 0
     256                 :             :          exit
     257                 :             :        end if
     258                 :             : 
     259                 :             :      end do     ! ikpt2
     260                 :             : 
     261                 :          21 :      if (flag == 1) then
     262                 :           0 :        write(msg,'(a,i0)')' Could not find a symmetric k-point for ikpt3=  ',ikpt3
     263                 :           0 :        ABI_BUG(msg)
     264                 :             :      end if
     265                 :             :    end do    ! ikpt3
     266                 :             : 
     267                 :             :  else
     268                 :           0 :    ABI_ERROR(' the only values for kptopt that are allowed are 2 and 3 ')
     269                 :             :  end if   ! condition on kptopt
     270                 :             : 
     271                 :             : 
     272                 :             : !--------- Compute the weights required for the Marzari-Vanderbilt ---------
     273                 :             : !--------- finite difference formula ---------------------------------------
     274                 :             : 
     275                 :             : 
     276                 :             : !Initialize distance between k-points
     277                 :             : !The trace of gmet is an upper limit for its largest eigenvalue. Since the
     278                 :             : !components of the distance vectors do not exceed 1, 3. * Tr[gmet] is
     279                 :             : !an upper limit for the squared shell radius.
     280                 :             : !we take something two times larger to make a bug checking.
     281                 :          21 :  dist_ = 0._dp
     282         [ +  + ]:          84 :  do ii = 1,3
     283                 :          84 :    dist_ = dist_ + gmet(ii,ii)
     284                 :             :  end do
     285                 :          21 :  max_dist = 3._dp * dist_ * 2._dp
     286                 :          21 :  write(std_out,*)'max_dist',max_dist
     287                 :             : 
     288                 :             : !Calculate an upper limit for the residuum
     289                 :             :  resdm = rmet(1,1)*rmet(1,1) + rmet(2,2)*rmet(2,2) + rmet(3,3)*rmet(3,3)&
     290                 :          21 : & + rmet(1,2)*rmet(1,2) + rmet(2,3)*rmet(2,3) + rmet(3,1)*rmet(3,1)
     291                 :             : 
     292                 :             : !Initialize shell loop
     293                 :          21 :  ishell = 0
     294                 :          21 :  last_dist = 0._dp
     295                 :          21 :  wtkflg = 0
     296   [ +  +  +  + ]:       20419 :  kneigh(:,:) = 0
     297   [ +  +  +  +  :       61278 :  kg_neigh(:,:,:) = 0
                   +  + ]
     298   [ +  +  +  + ]:        5285 :  neigh(:,:) = 0
     299                 :             : 
     300                 :             : !Loop over shells until the residuum is zero
     301   [ +  -  +  + ]:         115 :  do while ((wtkflg == 0).and.(resdm > tol8))
     302                 :             : !  Advance shell counter
     303                 :          94 :    ishell = ishell + 1
     304                 :             : 
     305                 :             : !  Initialize shell radius with upper limit
     306                 :          94 :    dist(ishell) = max_dist
     307                 :             : !  !!  border_flag = 1
     308                 :             : 
     309                 :             : !  !write(std_out,*)'gmet'
     310                 :             : !  !do ikpt=1,3
     311                 :             : !  !write(std_out,*)gmet(ikpt,:)
     312                 :             : !  !enddo
     313                 :             : !  !write(std_out,*)kpt3(:,1)
     314                 :             : 
     315                 :             : !  Find the (squared) radius of the next shell
     316         [ +  + ]:        2126 :    do ikpt = 1,nkpt3
     317                 :             : !    !write(std_out,*)ikpt
     318                 :             : !    !write(std_out,*)kpt3(:,ikpt)
     319         [ +  + ]:        8128 :      dk(:) = kpt3(:,1) - kpt3(:,ikpt)
     320                 :             : !    !!dk_(:) = dk(:) - nint(dk(:))
     321                 :             : !    !!dist_ = 0._dp
     322                 :             : !    !!do ii = 1,3
     323                 :             : !    !! do jj = 1,3
     324                 :             : !    !!  dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
     325                 :             : !    !! end do
     326                 :             : !    !!end do
     327                 :             : !    !!write(std_out,*)'dist_1', dist_
     328                 :             : !    !!   dist_ = 0._dp
     329                 :             : !    !!   do ii = 1,3
     330                 :             : !    !!    do jj = 1,3
     331                 :             : !    !!     dist_ = dist_ + dk(ii)*gmet(ii,jj)*dk(jj)
     332                 :             : !    !!    end do
     333                 :             : !    !!   end do
     334                 :             : !    !!write(std_out,*)'dist_2',dist_
     335         [ +  + ]:        6190 :      do coord1 = 0,1  !three loop to search also on the border of the BZ, ie for the k-points (1,k2,k3) and the likes
     336         [ +  + ]:       14224 :        do coord2 = 0,1
     337         [ +  + ]:       28448 :          do coord3 = 0,1
     338                 :             : !          !!      if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
     339                 :       65024 :            dist_ = 0._dp
     340         [ +  + ]:       65024 :            dk_(:) = dk(:) - nint(dk(:))
     341                 :       16256 :            dk_(1) = dk_(1) + real(coord1,dp)
     342                 :       16256 :            dk_(2) = dk_(2) + real(coord2,dp)
     343                 :       16256 :            dk_(3) = dk_(3) + real(coord3,dp)
     344         [ +  + ]:       65024 :            do ii = 1,3
     345         [ +  + ]:      211328 :              do jj = 1,3
     346                 :      195072 :                dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
     347                 :             :              end do
     348                 :             :            end do
     349                 :             : !          Note : for ipkt3 = 1, coord1 = coord2 = coord3 = 0, the distance is 0 ;
     350                 :             : !          but the next "if" statement is false with the tol8 criteria and the k-point
     351                 :             : !          should be ignored even for ishell = 1 and last_dist= 0.
     352                 :             : !          !$write(std_out,*)ikpt,coord1,coord2,coord3
     353                 :             : !          !$write(std_out,*)dk_
     354                 :             : !          !$write(std_out,*)'dist_2', dist_
     355                 :             : !          !!      end if
     356   [ +  +  +  + ]:       24384 :            if ((dist_ < dist(ishell)).and.(dist_ - last_dist > tol8)) then
     357                 :         360 :              dist(ishell) = dist_
     358                 :             :            end if
     359                 :             :          end do
     360                 :             :        end do
     361                 :             :      end do
     362                 :             : 
     363                 :             : !    !!   if ((dist_ < dist(ishell)).and.(dist_ - last_dist > tol8)) then
     364                 :             : !    !!    dist(ishell) = dist_
     365                 :             : !    !!    border_flag = 0
     366                 :             : !    !!   end if
     367                 :             :    end do
     368                 :             : 
     369                 :             : !  !!  if (border_flag==1) then !we haven't found any shell in the interior of the BZ, we need to search on the border
     370                 :             : !  !!write(std_out,*)ch10
     371                 :             : !  !!write(std_out,*)'search on the border'
     372                 :             : !  !!   do ikpt = 1,nkpt3
     373                 :             : !  !!    dk(:) = kpt3(:,1) - kpt3(:,ikpt)
     374                 :             : !  !!    do coord1 = 0,1
     375                 :             : !  !!     do coord2 = 0,1
     376                 :             : !  !!      do coord3 = 0,1
     377                 :             : !  !!       if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
     378                 :             : !  !!        dist_ = 0._dp
     379                 :             : !  !!        dk_(:) = dk(:) - nint(dk(:))
     380                 :             : !  !!        dk_(1) = dk_(1) + real(coord1,dp)
     381                 :             : !  !!        dk_(2) = dk_(2) + real(coord2,dp)
     382                 :             : !  !!        dk_(3) = dk_(3) + real(coord3,dp)
     383                 :             : !  !!        do ii = 1,3
     384                 :             : !  !!         do jj = 1,3
     385                 :             : !  !!          dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
     386                 :             : !  !!         end do
     387                 :             : !  !!        end do
     388                 :             : !  !!write(std_out,*)ikpt,coord1,coord2,coord3
     389                 :             : !  !!write(std_out,*)dk_
     390                 :             : !  !!write(std_out,*)'dist_2', dist_
     391                 :             : !  !!       end if
     392                 :             : !  !!       if ((dist_ < dist(ishell)).and.(dist_ - last_dist > tol8)) then
     393                 :             : !  !!        dist(ishell) = dist_
     394                 :             : !  !!       end if
     395                 :             : !  !!      end do
     396                 :             : !  !!     end do
     397                 :             : !  !!    end do
     398                 :             : !  !!   end do
     399                 :             : !  !!  endif
     400                 :             : 
     401                 :             : !  DEBUG
     402                 :             : !  !write(std_out,*)ch10
     403                 :             : !  write(std_out,*)'ishell, dist = ',ishell,dist(ishell)
     404                 :             : !  ENDDEBUG
     405                 :             : 
     406         [ -  + ]:          94 :    if (max_dist-dist(ishell)<tol8) then
     407                 :           0 :      write(msg,'(a,i0)')' Cannot find shell number',ishell
     408                 :           0 :      ABI_BUG(msg)
     409                 :             :    end if
     410                 :             : 
     411                 :        1111 :    last_dist = dist(ishell)
     412                 :             : 
     413                 :             : !  For each k-point in half the BZ get the shells of nearest neighbours.
     414                 :             : !  These neighbours can be out of the zone sampled by kpt2.
     415                 :             : !  !$write(std_out,*)'nkpt2', nkpt2, 'nkpt3', nkpt3
     416         [ +  + ]:        1111 :    do ikpt2 = 1, nkpt2              ! k-points in half the BZ
     417         [ +  + ]:        2393 :      orig = sum(neigh(0:ishell-1,ikpt2))
     418                 :             : !    !write(std_out,*)'ikpt2, orig', ikpt2,orig
     419                 :             : !    !write(std_out,*) kpt2(:,ikpt2)
     420                 :        1017 :      nneigh = 0
     421         [ +  + ]:      384289 :      do ikpt3 = 1, nkpt3             ! whole k-point grid
     422                 :             : !      !!    if(border_flag==0)then
     423         [ +  + ]:     1533088 :        dk(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
     424                 :             : !      !!     dk_(:) = dk(:) - nint(dk(:))
     425                 :             : !      !!     dist_ = 0._dp
     426         [ +  + ]:     1534105 :        do coord1 = -1,1
     427         [ +  + ]:     4982536 :          do coord2 = -1,1
     428         [ +  + ]:    14947608 :            do coord3 = -1,1
     429                 :             : !            !!        if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
     430                 :    41393376 :              dist_ = 0._dp
     431         [ +  + ]:    41393376 :              dk_(:) = dk(:) - nint(dk(:))
     432                 :    10348344 :              dk_(1) = dk_(1) + real(coord1,dp)
     433                 :    10348344 :              dk_(2) = dk_(2) + real(coord2,dp)
     434                 :    10348344 :              dk_(3) = dk_(3) + real(coord3,dp)
     435         [ +  + ]:    41393376 :              do ii = 1,3
     436         [ +  + ]:   134528472 :                do jj = 1,3
     437                 :   124180128 :                  dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
     438                 :             :                end do
     439                 :             :              end do
     440         [ +  + ]:    13797792 :              if (abs(dist_ - dist(ishell)) < tol8) then
     441                 :        4598 :                nneigh = nneigh + 1
     442                 :        4598 :                kneigh(orig+nneigh,ikpt2) = ikpt3
     443                 :        4598 :                kg_neigh(orig+nneigh,ikpt2,1) = coord1
     444                 :        4598 :                kg_neigh(orig+nneigh,ikpt2,2) = coord2
     445                 :        4598 :                kg_neigh(orig+nneigh,ikpt2,3) = coord3
     446                 :             :              end if
     447                 :             : !            !!        end if
     448                 :             :            end do
     449                 :             :          end do
     450                 :             :        end do
     451                 :             : !      !write(std_out,*)'ikpt3', ikpt3
     452                 :             : !      !write(std_out,*) kpt3(:,ikpt3)
     453                 :             : !      write(std_out,*) kpt2(:,ikpt2)
     454                 :             : !      !write(std_out,*) dk
     455                 :             : !      write(std_out,*) dk_
     456                 :             : !      !!     do ii = 1,3
     457                 :             : !      !!      do jj = 1,3
     458                 :             : !      !!       dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
     459                 :             : !      !!      end do
     460                 :             : !      !!     end do
     461                 :             : !      !write(std_out,*)'dist_', dist_
     462                 :             : !      !!     if (abs(dist_ - dist(ishell)) < tol8) then
     463                 :             : !      !!      nneigh = nneigh + 1
     464                 :             : !      !!      kneigh(orig+nneigh,ikpt2) = ikpt3
     465                 :             : !      !!     end if
     466                 :             : !      !!    else !search on the border
     467                 :             : !      !!     dk(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
     468                 :             : !      !!     do coord1 = -1,1
     469                 :             : !      !!      do coord2 = -1,1
     470                 :             : !      !!       do coord3 = -1,1
     471                 :             : !      !!        if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
     472                 :             : !      !!         dist_ = 0._dp
     473                 :             : !      !!         dk_(:) = dk(:) - nint(dk(:))
     474                 :             : !      !!         dk_(1) = dk_(1) + real(coord1,dp)
     475                 :             : !      !!         dk_(2) = dk_(2) + real(coord2,dp)
     476                 :             : !      !!         dk_(3) = dk_(3) + real(coord3,dp)
     477                 :             : !      !!         do ii = 1,3
     478                 :             : !      !!          do jj = 1,3
     479                 :             : !      !!           dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
     480                 :             : !      !!          end do
     481                 :             : !      !!         end do
     482                 :             : !      !!         if (abs(dist_ - dist(ishell)) < tol8) then
     483                 :             : !      !!          nneigh = nneigh + 1
     484                 :             : !      !!          kneigh(orig+nneigh,ikpt2) = ikpt3
     485                 :             : !      !!          kneigh_border(orig+nneigh,ikpt2,1) = real(coord1,dp)
     486                 :             : !      !!          kneigh_border(orig+nneigh,ikpt2,2) = real(coord2,dp)
     487                 :             : !      !!          kneigh_border(orig+nneigh,ikpt2,3) = real(coord3,dp)
     488                 :             : !      !!         end if
     489                 :             : !      !!        end if
     490                 :             : !      !!       end do
     491                 :             : !      !!      end do
     492                 :             : !      !!     end do
     493                 :             : !      !!    end if
     494                 :             :      end do
     495                 :        1111 :      neigh(ishell,ikpt2) = nneigh
     496                 :             :    end do
     497                 :             : 
     498                 :             : 
     499                 :             : !  Check if the number of points in shell number ishell
     500                 :             : !  is the same for each k-point
     501                 :             : 
     502                 :             :    flag = 1
     503         [ +  + ]:        1111 :    do ikpt = 1,nkpt2
     504         [ -  + ]:        1111 :      if (neigh(ishell,ikpt) /= nneigh) flag = 0
     505                 :             :    end do
     506                 :             : 
     507         [ -  + ]:          94 :    if (flag == 0) then
     508                 :             :      write(msg,'(a,i0,a,a)')&
     509                 :           0 :      ' The number of points in shell number',ishell,' is not the same',&
     510                 :           0 :      ' for each k-point.'
     511                 :           0 :      ABI_BUG(msg)
     512                 :             :    end if
     513                 :             : 
     514         [ -  + ]:          94 :    if (nneigh == 0) then
     515                 :           0 :      write(msg,'(a,a,a,a)') ch10,&
     516                 :           0 :      ' getshell: BUG - ',ch10,&
     517                 :           0 :      ' Cannot find enough neighbor shells'
     518                 :           0 :      call wrtout(unts, msg)
     519                 :           0 :      wtkflg = 1
     520                 :             :    end if
     521                 :             : 
     522                 :             : !  Calculate the total number of neighbors
     523         [ +  + ]:         261 :    nneigh = sum(neigh(1:ishell,1))
     524                 :             : !  DEBUG
     525                 :             :    !write(std_out,*)'ishell = ',ishell,'nneigh = ',nneigh
     526                 :             : !  ENDDEBUG
     527                 :             : 
     528                 :             : !  Find the weights needed to compute the finite difference expression
     529                 :             : !  of the ddk
     530                 :             : !  **********************************************************************
     531                 :             : 
     532                 :             : !  mvwtk(:,:) = 0._dp
     533                 :             : 
     534                 :             : !  The weights are calculated for ikpt=1. The results are copied later
     535                 :          94 :    ikpt = 1
     536                 :             : 
     537                 :             : !  Calculate the coefficients of the linear system to be solved
     538                 :          94 :    mat(:,:) = 0._dp
     539         [ +  + ]:         261 :    do is1 = 1, ishell
     540         [ +  + ]:         407 :      orig = sum(neigh(0:is1-1,ikpt))
     541                 :         167 :      bis = orig + neigh(is1,ikpt)
     542         [ +  + ]:         663 :      do ineigh = orig+1, bis
     543         [ +  + ]:        1608 :        dk_(:) = kpt3(:,kneigh(ineigh,ikpt)) - kpt2(:,ikpt)
     544         [ +  + ]:        1608 :        dk(:) = dk_(:) - nint(dk_(:))
     545         [ +  + ]:        1608 :        dk(:) = dk(:) + real(kg_neigh(ineigh,ikpt,:),dp)
     546                 :         402 :        mat(1,is1) = mat(1,is1) + dk(1)*dk(1)
     547                 :         402 :        mat(2,is1) = mat(2,is1) + dk(2)*dk(2)
     548                 :         402 :        mat(3,is1) = mat(3,is1) + dk(3)*dk(3)
     549                 :         402 :        mat(4,is1) = mat(4,is1) + dk(1)*dk(2)
     550                 :         402 :        mat(5,is1) = mat(5,is1) + dk(2)*dk(3)
     551                 :         569 :        mat(6,is1) = mat(6,is1) + dk(3)*dk(1)
     552                 :             :      end do
     553                 :             :    end do
     554                 :             : 
     555                 :          94 :    rvec(1) = rmet(1,1)
     556                 :          94 :    rvec(2) = rmet(2,2)
     557                 :          94 :    rvec(3) = rmet(3,3)
     558                 :          94 :    rvec(4) = rmet(1,2)
     559                 :          94 :    rvec(5) = rmet(2,3)
     560                 :          94 :    rvec(6) = rmet(3,1)
     561                 :             : 
     562                 :             : !  DEBUG
     563                 :             :    !write(std_out,*) " mat(1:6, 1:ishell) : rmet(1:6) for all 6 products dx^2... dxdy..."
     564                 :             :    !do ii = 1, 6
     565                 :             :    !  write(std_out,*) mat(ii,1:ishell), ' : ', rvec(ii)
     566                 :             :    !end do
     567                 :             : !  ENDDEBUG
     568                 :             : 
     569                 :             : !  Solve the linear least square problem
     570                 :          94 :    call dgelss(6,ishell,1,mat,6,rvec,6,sgval,tol8,irank,work,30,info)
     571                 :             : 
     572         [ -  + ]:          94 :    if( info /= 0 ) then
     573                 :             :      write(msg,'(3a,i0,a)')&
     574                 :           0 :      ' Singular-value decomposition of the linear system determining the',ch10,&
     575                 :           0 :      ' weights failed (info).',info,ch10
     576                 :           0 :      ABI_COMMENT(msg)
     577                 :           0 :      wtkflg = 1
     578                 :             :    end if
     579                 :             : 
     580                 :             : !  Check that the system has maximum rank
     581         [ +  + ]:         115 :    if( irank == ishell ) then
     582                 :             : !    System has full rank. Calculate the residuum
     583                 :          29 :      s1 = resdm
     584                 :          29 :      resdm = 0._dp
     585         [ +  + ]:         166 :      do is1 = ishell + 1, 6
     586                 :         166 :        resdm = resdm + rvec(is1) * rvec(is1)
     587                 :             :      end do
     588                 :             : 
     589   [ +  -  -  - ]:          29 :      if( ishell == 6 .and. resdm > tol8 ) then
     590                 :             :        write(msg,'(4a)')&
     591                 :           0 :        ' Linear system determining the weights could not be solved',ch10,&
     592                 :           0 :        ' This should not happen.',ch10
     593                 :           0 :        ABI_COMMENT(msg)
     594                 :             :        wtkflg = 1
     595                 :             :      end if
     596                 :             :    else
     597                 :             : !    The system is rank deficient
     598                 :          65 :      ishell = ishell - 1
     599                 :             : !    DEBUG
     600                 :             :      !write(std_out,*) 'Shell not linear independent from previous shells. Skipped.'
     601                 :             : !    ENDDEBUG
     602                 :             :    end if
     603                 :             : 
     604                 :             : !  DEBUG
     605                 :             :    !write(std_out,*) "ishell, nneigh, irank, resdm ", ishell, nneigh, irank, resdm
     606                 :             : !  ENDDEBUG
     607                 :             : 
     608                 :             : !  end of loop over shells
     609                 :             :  end do
     610                 :             : 
     611                 :             : !Copy weights
     612                 :          21 :  ikpt=1
     613         [ +  + ]:          50 :  do is1 = 1, ishell
     614         [ +  + ]:          66 :    orig = sum(neigh(0:is1-1,ikpt))
     615                 :          29 :    bis = orig + neigh(is1,ikpt)
     616         [ +  + ]:         176 :    mvwtk(orig+1:bis,1) = rvec(is1)
     617                 :             :  end do
     618         [ +  + ]:         658 :  do ikpt = 2,nkpt2
     619         [ +  + ]:        4480 :    mvwtk(1:nneigh,ikpt) = mvwtk(1:nneigh,1)
     620                 :             :  end do  ! ikpt
     621                 :             : 
     622                 :             : !Report weights
     623                 :          21 :  write(std_out,*) 'Neighbors(1:ishell,1) ', neigh(1:ishell,1)
     624                 :          21 :  write(std_out,*) 'Weights (1:ishell) ', rvec(1:ishell)
     625                 :          21 :  write(std_out,*) mvwtk(1:nneigh,1)
     626                 :             : 
     627                 :             : !Check the computed weights
     628         [ +  - ]:          21 :  if (wtkflg == 0) then
     629                 :          21 :    max_err = zero
     630                 :          21 :    my_tol = five * tol6
     631         [ +  + ]:         679 :    do ikpt = 1, nkpt2
     632         [ +  + ]:        2653 :      do ii = 1,3
     633         [ +  + ]:        8554 :        do jj = 1,3
     634                 :        5922 :          s1 = 0._dp
     635         [ +  + ]:       41454 :          do ineigh = 1, nneigh
     636         [ +  + ]:      142128 :            dk_(:) = kpt3(:,kneigh(ineigh,ikpt)) - kpt2(:,ikpt)
     637         [ +  + ]:      142128 :            dk(:) = dk_(:) - nint(dk_(:))
     638         [ +  + ]:      142128 :            dk(:) = dk(:) + real(kg_neigh(ineigh,ikpt,:),dp)
     639                 :       41454 :            s1 = s1 + dk(ii)*dk(jj)*mvwtk(ineigh,ikpt)
     640                 :             :          end do
     641         [ -  + ]:        7896 :          if (abs(s1 - rmet(ii,jj)) > my_tol) then
     642                 :           0 :            max_err = max(max_err, abs(s1 - rmet(ii,jj)))
     643                 :           0 :            wtkflg = 1
     644                 :             :          end if
     645                 :             :        end do
     646                 :             :      end do
     647                 :             :    end do
     648                 :             : 
     649         [ +  - ]:          21 :    if (wtkflg /= 0) then
     650                 :           0 :      write(msg,'(5a, 2(a, es16.8))') ch10,&
     651                 :           0 :      ' getshell: BUG -',ch10,&
     652                 :           0 :      ' The calculated weights do not solve the linear system for all k-points.', ch10, &
     653                 :           0 :      " max_err: ", max_err, " > tolerance: ", my_tol
     654                 :           0 :      call wrtout(unts, msg)
     655                 :             :    end if
     656                 :             :  end if
     657                 :             : 
     658                 :             :  if (wtkflg /= 0) then
     659                 :             : 
     660                 :             :    msg = ' There is a problem with the finite difference expression of the ddk '//ch10&
     661                 :             :         //' If you are very close to a symmetric structure, you might be confusing the algorithm with'//ch10&
     662                 :           0 :         //' sets of k-points which are not quite part of the same shell. Try rectifying angles and acell.'
     663                 :           0 :    ABI_BUG(msg)
     664                 :             : 
     665                 :             :  else
     666                 :             : 
     667                 :          21 :    nshell = ishell
     668                 :             : 
     669                 :          21 :    write(msg,'(a,a,a,a,a,a,a,i3,a,a,f16.7)') ch10,&
     670                 :          21 :    ' getshell : finite difference formula of Marzari and Vanderbilt',ch10,&
     671                 :          21 :    '            (see Marzari and Vanderbilt, PRB 56, 12847 (1997), Appendix B)',& ! [[cite:Marzari1997]]
     672                 :          21 :    ch10,ch10,&
     673                 :          21 :    '            number of first neighbours  : ', neigh(1,1),ch10,&
     674                 :          42 :    '            weight : ',mvwtk(1,1)
     675                 :          21 :    call wrtout(unts, msg)
     676                 :             : 
     677         [ +  + ]:          21 :    if (nshell > 1) then
     678                 :           8 :      is1 = neigh(1,1) + 1
     679                 :           8 :      write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
     680                 :           8 :      '            number of second neighbours  : ', neigh(2,1),ch10,&
     681                 :          16 :      '            weight : ',mvwtk(is1,1)
     682                 :           8 :      call wrtout(unts, msg)
     683                 :             :    end if
     684                 :             : 
     685         [ -  + ]:           8 :    if (nshell > 2) then
     686         [ #  # ]:           0 :      is1 = sum(neigh(1:2,1)) + 1
     687                 :           0 :      write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
     688                 :           0 :       '            number of third neighbours  : ', neigh(3,1),ch10,&
     689                 :           0 :       '            weight : ',mvwtk(is1,1)
     690                 :           0 :      call wrtout(unts, msg)
     691                 :             :    end if
     692                 :             : 
     693         [ #  # ]:           0 :    if (nshell > 3) then
     694         [ #  # ]:           0 :      is1 = sum(neigh(1:3,1)) + 1
     695                 :           0 :      write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
     696                 :           0 :       '            number of fourth neighbours  : ', neigh(4,1),ch10,&
     697                 :           0 :       '            weight : ',mvwtk(is1,1)
     698                 :           0 :      call wrtout(unts, msg)
     699                 :             :    end if
     700                 :             : 
     701         [ #  # ]:           0 :    if (nshell > 4) then
     702         [ #  # ]:           0 :      is1 = sum(neigh(1:4,1)) + 1
     703                 :           0 :      write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
     704                 :           0 :       '            number of fifth neighbours  : ', neigh(5,1),ch10,&
     705                 :           0 :       '            weight : ',mvwtk(is1,1)
     706                 :           0 :      call wrtout(unts, msg)
     707                 :             :    end if
     708                 :             : 
     709         [ #  # ]:           0 :    if (nshell > 5) then
     710         [ #  # ]:           0 :      is1 = sum(neigh(1:5,1)) + 1
     711                 :           0 :      write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
     712                 :           0 :      '            number of sixth neighbours  : ', neigh(6,1),ch10,&
     713                 :           0 :      '            weight : ',mvwtk(is1,1)
     714                 :           0 :      call wrtout(unts, msg)
     715                 :             :    end if
     716                 :             : 
     717                 :             :  end if
     718                 :             : 
     719         [ +  - ]:          21 :  ABI_SFREE(tnons1)
     720         [ +  - ]:          21 :  ABI_SFREE(symrel1)
     721                 :             : 
     722         [ -  + ]:          21 :  ABI_FREE(wtk3)
     723                 :             : 
     724                 :          21 : end subroutine getshell
     725                 :             : !!***
     726                 :             : 
     727                 :             : end module m_getshell
     728                 :             : !!***
        

Generated by: LCOV version 2.3-1