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-09-19 15:24:51 Functions: 100.0 % 1 1

            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