TABLE OF CONTENTS


ABINIT/m_bz_mesh [ Modules ]

[ Top ] [ Modules ]

NAME

  m_bz_mesh

FUNCTION

  This module provides the definition of the kmesh_t structure gathering information
  on the sampling of the Brillouin zone. It also contains useful tools to operate on k-points.
  and the definition of the littlegroup_t data type. The littlegroup_t structure is used
  to store tables and useful info on the set of k-points belonging
  to the irreducible wedge defined by the symmetry properties
  of the point group that preserve the external q-point.

COPYRIGHT

 Copyright (C) 2008-2024 ABINIT group (MG, GMR, VO, LR, RWG, MT)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

NOTES

  One has to use a fixed ordering of the loops over nsym and time-reversal
  when the full zone is reconstructed by symmetry starting from the IBZ.
  This is especially important in systems with both time-reversal and
  spatial inversion as the effect of the two operation in reciprocal
  space is very similar the only difference being the possibly non-zero
  fractional translation associated to the spatial inversion.
  In the present implementation, the spatial inversion has the precedence
  wrt time-reversal (i.e., do itim; do isym).
  Note that this particular ordering should be used in any routine used to
  symmetrize k-dependent quantities in the full BZ zone to avoid possible errors.

  * This module is deprecated and should be used only in the GW/BSE part.
    Some of the routines will be gradually moved to m_kpts

SOURCE

36 #if defined HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39 
40 #include "abi_common.h"
41 
42 module m_bz_mesh
43 
44  use defs_basis
45  use m_errors
46  use m_abicore
47  use m_sort
48  use m_xmpi
49 
50  use m_fstrings,       only : ltoa, itoa, sjoin, ktoa
51  use m_numeric_tools,  only : is_zero, isinteger, imin_loc, imax_loc, bisect, wrap2_pmhalf
52  use m_symtk,          only : sg_multable, littlegroup_q
53  use m_geometry,       only : normv
54  use m_crystal,        only : crystal_t
55  use m_kpts,           only : getkgrid
56  use m_symkpt,         only : symkpt
57 
58  implicit none
59 
60  private
61 
62  real(dp),parameter :: TOL_KDIFF = 0.0001_dp
63  ! Tolerance below which two points are considered equal within a RL vector:
64  ! for each reduced direction the absolute difference between the coordinates must be less that TOL_KDIFF
65 
66  integer,parameter :: NONE_KPTRLATT(3,3) = RESHAPE((/0,0,0,0,0,0,0,0,0/),(/3,3/))

m_bz_mesh/box_len [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

  box_len

FUNCTION

   Given a direction in q-space defined by the q-point qpt, this function returns
   the length of the vector connecting the origin with one the faces of the cell
   defined by the lattice vectors gprimd.

INPUTS

   qpt(3)=The reduced coordinates of the q-point defining the direction. Normalization is not mandatory.
   gprimd(3,3)=Cartesian coordinates of the vectors defining the lattice.

SOURCE

2715 function box_len(qpt, gprimd)
2716 
2717 !Arguments ------------------------------------
2718 !scalars
2719  real(dp) :: box_len
2720 !arrays
2721  real(dp),intent(in) :: qpt(3),gprimd(3,3)
2722 
2723 !Local variables-------------------------------
2724 !scalars
2725  integer :: idir,iplane
2726  real(dp) :: x1,x2,x3
2727 !arrays
2728  real(dp) :: my_qpt(3),gmet(3,3),q0box(3)
2729 
2730 ! *************************************************************************
2731 
2732  ! Compute reciprocal space metric
2733  gmet = MATMUL(TRANSPOSE(gprimd),gprimd)
2734 
2735  ! Rotate the input q-point such that it is always in the first octant then normalize it.
2736  ! Bravais lattices are invariant under inversion of any of the basis vectors.
2737  my_qpt = ABS(qpt)/normv(qpt,gmet,"G")
2738 
2739  ! Check whether the q is along one of the reduced directions.
2740  idir=0; if (COUNT(ABS(qpt)<tol16) == 2) idir = imax_loc(ABS(qpt))
2741 
2742  if (idir/=0) then ! easy as q is along vector idir.
2743    box_len =  normv(gprimd(:,idir), gmet, "G")
2744    RETURN
2745 
2746  else
2747    !iplane/=0 means that q is placed on one the planes defined by two reciprocal lattice vectors.
2748    iplane=0; if (COUNT(ABS(qpt)<tol16) == 1) iplane = imin_loc(ABS(qpt))
2749    q0box = [-1,-1,-1]
2750 
2751    if (iplane/=1) then
2752      x1=one
2753      x2=my_qpt(2)/my_qpt(1)
2754      x3=my_qpt(3)/my_qpt(1)
2755      if (x2<=one+tol16 .and. x3<=one+tol16) q0box=(/x1,x2,x3/)
2756    end if
2757    if (iplane/=2) then
2758      x1=my_qpt(1)/my_qpt(2)
2759      x2=one
2760      x3=my_qpt(3)/my_qpt(2)
2761      if (x1<=one+tol16 .and. x3<=one+tol16) q0box=(/x1,x2,x3/)
2762    end if
2763    if (iplane/=3) then
2764      x1=my_qpt(1)/my_qpt(3)
2765      x2=my_qpt(2)/my_qpt(3)
2766      x3=one
2767      if (x1<=one+tol16 .and. x2<=one+tol16) q0box=(/x1,x2,x3/)
2768    end if
2769 
2770    if (ALL(q0box == [-1,-1,-1])) then
2771      ABI_BUG("Cannot found q0box")
2772    end if
2773 
2774    box_len = normv(q0box,gmet,"G")
2775    RETURN
2776  end if
2777 
2778 end function box_len

m_bz_mesh/bz_mesh_isirred [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 bz_mesh_isirred

FUNCTION

  bz_mesh_isirred

INPUTS

  ik_bz=Index of the k-point in the BZ.

OUTPUT

 bz_mesh_isirred=.TRUE. if the k-point is in the IBZ (a non-zero umklapp is not allowed)

SOURCE

1230 pure logical function bz_mesh_isirred(Kmesh, ik_bz)
1231 
1232 !Arguments ------------------------------------
1233 !scalars
1234  class(kmesh_t),intent(in) :: Kmesh
1235  integer,intent(in) :: ik_bz
1236 
1237 !Local variables-------------------------------
1238 !scalars
1239  integer :: isym,itim
1240 
1241 ! *********************************************************************
1242 
1243  isym = Kmesh%tabo(ik_bz)
1244  itim = (3-Kmesh%tabi(ik_bz))/2
1245 
1246  ! Be careful here as we assume a particular ordering of symmetries.
1247  bz_mesh_isirred = ( isym==1.and.itim==1.and.ALL(Kmesh%umklp(:,ik_bz)==(/0,0,0/)) )
1248 
1249 end function bz_mesh_isirred

m_bz_mesh/find_qmesh [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 find_qmesh

FUNCTION

  Find the q-mesh defined as all the possible differences between k-points
  Find the irreducible q-points using a special treatment for the Gamma point.
  Then call setup_kmesh to initialize the Qmesh datatype

INPUTS

  Cryst<crystal_t>=datatype gathering info on the unit cell and symmetries
    %nsym=number of symmetry operations
    %symrec(3,3,nsym)=symmetry operations in reciprocal space
  Kmesh<kmesh_t>=datatype gathering information on the k-mesh

OUTPUT

  Qmesh<kmesh_t>=datatype gathering information on the q point sampling.

SOURCE

1887 subroutine find_qmesh(Qmesh,Cryst,Kmesh)
1888 
1889 !Arguments ------------------------------------
1890 !scalars
1891  type(kmesh_t),intent(in) :: Kmesh
1892  type(kmesh_t),intent(inout) :: Qmesh
1893  type(crystal_t),intent(in) :: Cryst
1894 
1895 !Local variables-------------------------------
1896 !scalars
1897  integer :: nqibz,kptopt
1898 !arrays
1899  real(dp),allocatable :: qibz(:,:)
1900 
1901 ! *************************************************************************
1902 
1903  !@kmesh_t
1904  ! * Find the number of q-points such that q = k1-k2.
1905  call findnq(Kmesh%nbz,Kmesh%bz,Cryst%nsym,Cryst%symrec,Cryst%symafm,nqibz,Cryst%timrev)
1906  !
1907  ! * Find the coordinates of the q-points in the IBZ.
1908  ABI_MALLOC(qibz,(3,nqibz))
1909  call findq(Kmesh%nbz,Kmesh%bz,Cryst%nsym,Cryst%symrec,Cryst%symafm,Cryst%gprimd,nqibz,qibz,Cryst%timrev)
1910  !
1911  ! * Create the Qmesh object starting from the IBZ.
1912  kptopt = Kmesh%kptopt
1913  call kmesh_init(Qmesh,Cryst,nqibz,qibz,kptopt)
1914 
1915  ABI_FREE(qibz)
1916 
1917 end subroutine find_qmesh

m_bz_mesh/findnq [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 findnq

FUNCTION

 Identify the number of q-points in the IBZ by which the k-points in BZ differ
 (count the q points in the k-point difference set)

INPUTS

  nkbz=number of k points in Brillouin zone
  kbz(3,nkbz)=coordinates of k points in BZ
  nsym=number of symmetry operations
  symrec(3,3,nsym)=symmetry operations in reciprocal space
  symafm(nsym)=-1 if AFM symmetry.
  timrev=2 if time-reversal symmetry is used, 1 otherwise

OUTPUT

  nqibz=number of q points

SOURCE

1943 subroutine findnq(nkbz,kbz,nsym,symrec,symafm,nqibz,timrev)
1944 
1945 !Arguments ------------------------------------
1946 !scalars
1947  integer,intent(in) :: timrev,nkbz,nsym
1948  integer,intent(out) :: nqibz
1949 !arrays
1950  integer,intent(in) :: symrec(3,3,nsym),symafm(nsym)
1951  real(dp),intent(in) :: kbz(3,nkbz)
1952 
1953 !Local variables ------------------------------
1954 !scalars
1955  integer :: ifound,ik,isym,iq,memory_exhausted,nqall,nqallm,itim,ierr
1956 !arrays
1957  integer :: g0(3)
1958  real(dp) :: qposs(3),qrot(3)
1959  real(dp),allocatable :: qall(:,:)
1960 !************************************************************************
1961 
1962  ! Infinite do-loop to be able to allocate sufficient memory
1963  nqallm=1000
1964  do
1965    memory_exhausted=0
1966    ABI_MALLOC_OR_DIE(qall,(3,nqallm), ierr)
1967    nqall=0
1968 
1969    ! Loop over all k-points in BZ, forming k-k1.
1970    do ik=1,nkbz
1971      qposs(:)=kbz(:,ik)-kbz(:,1)
1972 
1973      ! Check whether this q (or its equivalent) has already been found within a reciprocal lattice vector.
1974      ! Use spatial inversion instead of time reversal whenever possible.
1975      ifound=0
1976      do iq=1,nqall
1977        do itim=1,timrev
1978          do isym=1,nsym
1979            if (symafm(isym)==-1) CYCLE
1980            qrot = (3-2*itim) * MATMUL(symrec(:,:,isym),qall(:,iq))
1981            if (isamek(qrot,qposs,g0)) ifound=ifound+1
1982          end do
1983        end do
1984      end do
1985 
1986      if (ifound==0) then
1987        nqall=nqall+1
1988 
1989        ! If not yet found, check that the allocation is big enough.
1990        if (nqall>nqallm) then
1991          memory_exhausted=1
1992          ABI_FREE(qall)
1993          nqallm=nqallm*2; EXIT ! Exit the do ik=1 loop
1994        end if
1995 
1996        !  Add it to the list.
1997        qall(:,nqall)=qposs(:)
1998      end if
1999    end do
2000 
2001    if (memory_exhausted==0) EXIT
2002  end do !infinite loop
2003 
2004  ABI_FREE(qall)
2005  nqibz=nqall
2006 
2007 end subroutine findnq

m_bz_mesh/findq [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 findq

FUNCTION

 Identify the q-points by which the k-points in BZ differ

INPUTS

  nkbz=number of k points in Brillouin zone
  kbz(3,nkbz)=coordinates of k points in BZ
  nsym=number of symmetry operations
  symrec(3,3,nsym)=symmetry operations in reciprocal space
  symafm(nsym)=-1 is symmetry is AFM, +1 otherwise.
  gprimd(3,3)=dimensional reciprocal space primitive translations
  nqibz=number of q points in the IBZ by which k points differ (computed in findnq)
  timrev=2 if time-reversal symmetry is used, 1 otherwise

OUTPUT

  qibz(3,nqibz)=coordinates of q points by which k points differ

SOURCE

2035 subroutine findq(nkbz,kbz,nsym,symrec,symafm,gprimd,nqibz,qibz,timrev)
2036 
2037 !Arguments ------------------------------------
2038 !scalars
2039  integer,intent(in) :: nkbz,nqibz,nsym,timrev
2040 !arrays
2041  integer,intent(in) :: symrec(3,3,nsym),symafm(nsym)
2042  real(dp),intent(in) :: gprimd(3,3),kbz(3,nkbz)
2043  real(dp),intent(inout) :: qibz(3,nqibz) !vz_i num m_numeric_tools
2044 
2045 !Local variables ------------------------------
2046 !scalars
2047  integer :: ii,ik,iq,iqp,isym,itim
2048  real(dp) :: shift1,qred
2049  logical :: found
2050  character(len=500) :: msg
2051 !arrays
2052  integer :: g0(3)
2053  real(dp) :: gmet(3,3),qposs(3),qrot(3)
2054 
2055 !************************************************************************
2056 
2057  ! Compute reciprocal space metrics
2058  do ii=1,3
2059    gmet(ii,:)=gprimd(1,ii)*gprimd(1,:)+&
2060 &             gprimd(2,ii)*gprimd(2,:)+&
2061 &             gprimd(3,ii)*gprimd(3,:)
2062  end do
2063  !
2064  ! === Loop over k-points in BZ, form k-k1 and translate in first BZ ===
2065  ! iq is the no. of q-points found, zero at the beginning
2066  iq=0
2067  do ik=1,nkbz
2068    qposs(:)=kbz(:,ik)-kbz(:,1)
2069    ! === Check whether this q (or its equivalent) has already been found ===
2070    ! * Use spatial inversion instead of time reversal whenever possible.
2071    found=.FALSE.
2072    do iqp=1,iq
2073      do itim=1,timrev
2074        do isym=1,nsym
2075         if (symafm(isym)==-1) CYCLE
2076         qrot = (3-2*itim) * MATMUL(symrec(:,:,isym),qibz(:,iqp))
2077         if (isamek(qrot,qposs,g0)) found=.TRUE.
2078        end do
2079      end do
2080    end do
2081    if (.not.found) then
2082      iq=iq+1
2083      if (iq>nqibz) then
2084        ABI_BUG(sjoin('iq > nqibz= ',itoa(nqibz)))
2085      end if
2086      qibz(:,iq)=qposs(:)
2087    end if
2088  end do
2089 
2090  if (iq/=nqibz) then
2091    write(msg,'(2(a,i5))')' iq= ',iq,'/= nqibz= ',nqibz
2092    ABI_BUG(msg)
2093  end if
2094  !
2095  ! * Translate q-points to 1st BZ in the interval [-1/2,1/2[
2096  do iq=1,nqibz
2097    do ii=1,3
2098      call wrap2_pmhalf(qibz(ii,iq),qred,shift1)
2099      qibz(ii,iq)=qred
2100    end do
2101  end do
2102 
2103 end subroutine findq

m_bz_mesh/findqg0 [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 findqg0

FUNCTION

 Identify q + g0 = k - kp

INPUTS

  kmkp(3)= k - kp input vector
  nqbz=number of q points in the BZ
  qbz(3,nqbz)=coordinates of q-points in the BZ
  mG0(3)= For each reduced direction gives the maximum G0 component to account for umklapp processes

OUTPUT

  iq=index of q in qbz array.
  g0(3)=reciprocal space vector, to be used in igfft

SOURCE

2127 subroutine findqg0(iq, g0, kmkp, nqbz, qbz, mG0)
2128 
2129 !Arguments ------------------------------------
2130 !scalars
2131  integer,intent(in) :: nqbz
2132  integer,intent(out) :: iq
2133 !arrays
2134  integer,intent(in) :: mG0(3)
2135  integer,intent(out) :: g0(3)
2136  real(dp),intent(in) :: kmkp(3),qbz(3,nqbz)
2137 
2138 !Local variables-------------------------------
2139 !FIXME if I use 1.0d-4 the jobs crash, should understand why
2140 !scalars
2141  integer :: ig,iqbz,jg01,jg02,jg03
2142  real(dp) :: tolq0=1.0D-3
2143  character(len=500) :: msg
2144 !arrays
2145  real(dp) :: glist1(2*ABS(mG0(1))+1),glist2(2*ABS(mG0(2))+1),glist3(2*ABS(mG0(3))+1)
2146  real(dp) :: qpg0(3),rg(3)
2147 
2148 ! *************************************************************************
2149 
2150  iq = 0
2151 
2152  if (ALL(ABS(kmkp) < EPSILON(one))) then
2153    ! Find q close to 0
2154    do iqbz=1,nqbz
2155      if (ALL(ABS(qbz(:,iqbz)) < tolq0)) then
2156        iq = iqbz
2157      end if
2158    end do
2159 
2160    ABI_CHECK(iq /= 0, 'Wrong list of q-points: q=0 not present.')
2161    g0(:) = 0; RETURN
2162 
2163  else
2164    ! q is not zero, find q such as k-kp=q+G0.
2165 
2166    ! Try with G0 = 0 first.
2167    !do iqbz=1,nqbz
2168    !  if (ALL(ABS(qbz(:,iqbz)-kmkp)<TOL_KDIFF)) then
2169    !    iq=iqbz
2170    !    g0(:)=0; RETURN
2171    !  end if
2172    !end do
2173 
2174    ! Init G0 lists to accelerate search below (small |G0| first)
2175    glist1(1) = 0
2176    ig = 2
2177    do jg01=1,mG0(1)
2178      glist1(ig)   =  jg01
2179      glist1(ig+1) = -jg01
2180      ig = ig + 2
2181    end do
2182 
2183    glist2(1) = 0
2184    ig = 2
2185    do jg02=1,mG0(2)
2186      glist2(ig)   =  jg02
2187      glist2(ig+1) = -jg02
2188      ig = ig + 2
2189    end do
2190 
2191    glist3(1) = 0
2192    ig = 2
2193    do jg03=1,mG0(3)
2194      glist3(ig)   =  jg03
2195      glist3(ig+1) = -jg03
2196      ig = ig + 2
2197    end do
2198 
2199   ! Search algorithm.
2200   g1loop: do jg01=1,2*mG0(1)+1
2201     rg(1) = glist1(jg01)
2202     do jg02=1,2*mG0(2)+1
2203       rg(2) = glist2(jg02)
2204       do jg03=1,2*mG0(3)+1
2205          rg(3) = glist3(jg03)
2206 
2207          ! Form q+G0 and check if it is the one.
2208          do iqbz=1,nqbz
2209           qpg0= qbz(:,iqbz) + rg
2210           if (ALL(ABS(qpg0-kmkp) < TOL_KDIFF)) then
2211             iq = iqbz
2212             g0 = NINT(rg)
2213             EXIT g1loop
2214           end if
2215         end do
2216 
2217       end do
2218     end do
2219   end do g1loop
2220 
2221   if (iq == 0) then
2222     write(msg,'(a, 3f9.5)')' q = k-kp+G0 not found. kmkp:',kmkp
2223     ABI_ERROR(msg)
2224   end if
2225  end if
2226 
2227 end subroutine findqg0

m_bz_mesh/get_BZ_diff [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 get_BZ_diff

FUNCTION

 Given two points k1 and k2 where k1 belongs to the BZ, check if the difference
 k1-k2 still belongs to the BZ reporting useful quantities

INPUTS

  Kmesh<kmesh_t>=datatype gathering information on the k-mesh
  k1(3)=the first k-points (supposed to be in the BZ)
  k2(3)=the second point

OUTPUT

  idiff_bz=the idex of k1-k2 in the BZ
  G0(3)=the umklapp G0 vector required to bring k1-k2 back to the BZ
  nfound= the number of points in the BZ that are equal to k1-k2 (should be 1 if everything is OK)

SOURCE

 967 subroutine get_BZ_diff(Kmesh,k1,k2,idiff_bz,g0,nfound)
 968 
 969 !Arguments ------------------------------------
 970 !scalars
 971  class(kmesh_t),intent(in) :: Kmesh
 972  integer,intent(out) :: idiff_bz,nfound
 973 !arrays
 974  integer,intent(out) :: g0(3)
 975  real(dp),intent(in) :: k1(3),k2(3)
 976 
 977 !Local variables-------------------------------
 978 !scalars
 979  integer :: ikp
 980  character(len=500) :: msg
 981 !arrays
 982  integer :: umklp(3)
 983  real(dp) :: kdiff(3),ktrial(3)
 984 
 985 ! *********************************************************************
 986 
 987  if (.not.has_BZ_item(Kmesh,k1,ikp,umklp)) then
 988    write(msg,'(a,3f12.6)')' first point must be in BZ: ',k1
 989    ABI_ERROR(msg)
 990  end if
 991 
 992  kdiff   = k1-k2
 993  nfound  = 0
 994  idiff_bz= 0
 995  !
 996  ! === Find p such k1-k2=p+g0 where p in the BZ ===
 997  do ikp=1,Kmesh%nbz
 998    ktrial=Kmesh%bz(:,ikp)
 999    if (isamek(kdiff,ktrial,umklp)) then
1000      idiff_bz=ikp
1001      g0=umklp
1002      nfound=nfound+1
1003    end if
1004  end do
1005  !
1006  ! === Check if p has not found of found more than once ===
1007  ! * For extremely dense meshes, tol1q in defs_basis might be too large!
1008  if (nfound/=1) then
1009    if (nfound==0) then
1010      ABI_WARNING(" k1-k2-G0 not found in BZ")
1011    else
1012      ABI_WARNING(sjoin(' Multiple k1-k2-G0 found in BZ, nfound= ', itoa(nfound)))
1013    end if
1014    write(msg,'(4a,3(a,3f12.6,a))')&
1015 &    ' k1    = ',k1   ,ch10,&
1016 &    ' k2    = ',k2   ,ch10,&
1017 &    ' k1-k2 = ',kdiff,ch10
1018    ABI_WARNING(msg)
1019  end if
1020 
1021 end subroutine get_BZ_diff

m_bz_mesh/get_bz_item [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 get_bz_item

FUNCTION

 Given the index of a point in the full BZ, this routine returns the index of the
 symmetric image in the IBZ, the index of the symmetry operation symrec needed,
 whether time-reversal has to be used.
 Optionally the non-symmorphic phase and the umklapp vector is returned.

INPUTS

 ikbz=The index of the required point in the BZ
 Kmesh<kmesh_t>=Datatype gathering information on the k point sampling.

OUTPUT

 kbz(3)=The k-point in the first BZ in reduced coordinated.
 isym=Index of the symrec symmetry required to rotate ik_ibz onto ik_bz.
 itim=2 is time-reversal has to be used, 1 otherwise
 ik_ibz=The index of the corresponding symmetric point in the IBZ.
 [ph_mkbzt]=The phase factor for non-symmorphic operations  e^{-i 2 \pi k_IBZ \cdot R{^-1}t}=e{-i 2\pi k_BZ cdot t}
 [umklp(3)]=The umklapp G0 vector such as kbz + G0 = (IS) k_ibz, where kbz is in the BZ.
 [isirred]=.TRUE. if the k-point belongs to IBZ.

SOURCE

864 subroutine get_bz_item(Kmesh,ik_bz,kbz,ik_ibz,isym,itim,ph_mkbzt,umklp,isirred)
865 
866 !Arguments ------------------------------------
867 !scalars
868  class(kmesh_t),intent(in) :: Kmesh
869  integer,intent(in) :: ik_bz
870  integer,intent(out) :: ik_ibz,isym,itim
871  complex(dpc),optional,intent(out) :: ph_mkbzt
872  logical,optional,intent(out) :: isirred
873 !arrays
874  integer,optional,intent(out) :: umklp(3)
875  real(dp),intent(out) :: kbz(3)
876 
877 !Local variables-------------------------------
878 !scalars
879  character(len=500) :: msg
880 
881 ! *********************************************************************
882 
883  if (ik_bz>Kmesh%nbz.or.ik_bz<=0) then
884    write(msg,'(a,2i3)')' Wrong value for ik_bz: ',ik_bz,Kmesh%nbz
885    ABI_BUG(msg)
886  end if
887 
888  kbz    = Kmesh%bz(:,ik_bz)
889  ik_ibz = Kmesh%tab(ik_bz)
890  isym   = Kmesh%tabo(ik_bz)
891  itim   = (3-Kmesh%tabi(ik_bz))/2
892 
893  if (PRESENT(ph_mkbzt)) ph_mkbzt=Kmesh%tabp(ik_bz)
894  if (PRESENT(umklp))    umklp   =Kmesh%umklp(:,ik_bz)
895  ! Be careful here as we assume a particular ordering of symmetries.
896  if (PRESENT(isirred))  isirred = (isym==1.and.itim==1.and.ALL(Kmesh%umklp(:,ik_bz)==(/0,0,0/)))
897 
898 end subroutine get_bz_item

m_bz_mesh/get_IBZ_item [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 get_IBZ_item

FUNCTION

 Report useful information on a k-point in the IBZ starting from its sequential index in %ibz.

INPUTS

 ik_ibz=The index of the required point in the IBZ
 Kmesh<kmesh_t>=datatype gathering information on the k point sampling.

OUTPUT

 kibz(3)=the k-point in reduced coordinated
 wtk=the weight

TODO

  Add mapping ibz2bz, ibz2star

SOURCE

923 subroutine get_IBZ_item(Kmesh,ik_ibz,kibz,wtk)
924 
925 !Arguments ------------------------------------
926 !scalars
927  class(kmesh_t),intent(in) :: Kmesh
928  integer,intent(in) :: ik_ibz
929  real(dp),intent(out) :: wtk
930 !arrays
931  real(dp),intent(out) :: kibz(3)
932 
933 ! *********************************************************************
934 
935  if (ik_ibz>Kmesh%nibz.or.ik_ibz<=0) then
936    ABI_BUG(sjoin('wrong value for ik_ibz: ',itoa(ik_ibz)))
937  end if
938 
939  kibz=Kmesh%ibz(:,ik_ibz)
940  wtk =Kmesh%wt(ik_ibz)
941 
942 end subroutine get_IBZ_item

m_bz_mesh/get_ng0sh [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 get_ng0sh

FUNCTION

  Given two lists of k-points, kbz1 and kbz2, calculate any possible difference k1-k2.
  For each difference, find the umklapp g0 vector and the point k3 in the array kfold
  such as k1-k2 = k3 + G0.
  The optimal value of G0 shells is returned, namely the smallest box around Gamma
  which suffices to treat all possible umklapp processes.
  The search algorithm uses bisection to process to scale in nk1*nk2*log(nkfold)

INPUTS

  nk1, nk2=Number of points in the arrays kbz1, kbz2.
  kbz1(3,nk1)=Reduced coordinates of the first set of points.
  kbz2(3,nk2)=Reduced coordinates of the second set of points.
  nkfold=Number of points in the array kfold.
  kfold(3,nkfol)=Reduced coordinated of the points in the BZ.
  tolq0=Tolerance below which a q-point is treated as zero.

OUTPUT

  opt_ng0(3)=Minimal reduced components of the G0 vectors to account for umklapps.

SOURCE

1600 subroutine get_ng0sh(nk1,kbz1,nk2,kbz2,nkfold,kfold,tolq0,opt_ng0)
1601 
1602 !Arguments ------------------------------------
1603 !scalars
1604  integer,intent(in) :: nk1,nk2,nkfold
1605  real(dp),intent(in) :: tolq0
1606 !arrays
1607  integer,intent(out) :: opt_ng0(3)
1608  real(dp),intent(in) :: kbz1(3,nk1),kbz2(3,nk2),kfold(3,nkfold)
1609 
1610 !Local variables-------------------------------
1611 !scalars
1612  integer :: i1,i2,ikf,ind,factor
1613  real(dp) :: normdiff,tempnorm,smallestlen
1614  logical :: found
1615  character(len=500) :: msg
1616 !arrays
1617  integer :: roundk(3),kbigdiff(3),kbigfold(3,nkfold),iperm(nkfold)
1618  real(dp) :: k1mk2(3),ksmalldiff(3),norm(nkfold),ksmallfold(3,nkfold)
1619 
1620 !************************************************************************
1621 
1622  ! Compute smallest length of one component
1623  ! To get a sufficiently large factor to order vectors
1624  smallestlen = one
1625 
1626  ! Compute integer part and fractional part, [0,1[ of kfold
1627  do ikf = 1,nkfold
1628    kbigfold(:,ikf) = FLOOR(kfold(:,ikf)+tol7)
1629    ksmallfold(:,ikf) = kfold(:,ikf)-kbigfold(:,ikf)
1630 
1631    if (ABS(ksmallfold(1,ikf)) > tol7) &
1632 &     smallestlen = MIN(smallestlen, ABS(ksmallfold(1,ikf)))
1633    if (ABS(ksmallfold(2,ikf)) > tol7) &
1634 &     smallestlen = MIN(smallestlen, ABS(ksmallfold(2,ikf)))
1635    if (ABS(ksmallfold(3,ikf)) > tol7) &
1636 &     smallestlen = MIN(smallestlen, ABS(ksmallfold(3,ikf)))
1637 
1638  end do
1639 
1640  ! WARNING ! This could not be sufficient if tested k1 - k2 has lower
1641  ! components than smallestlen. The factor 10 is giving us a security margin.
1642  factor = 10*(int(one/smallestlen)+1)
1643 
1644  ! Loop again over kfold vectors to give each term its norm
1645  do ikf=1, nkfold
1646    iperm(ikf) = ikf
1647 
1648    ! Computing a sort of norm with order of components (used for ordering)
1649    call getkptnorm_bycomponent(ksmallfold(:,ikf),factor,tempnorm)
1650 
1651    norm(ikf) = tempnorm
1652  end do
1653 
1654  ! Sorting list of kfold vectors
1655  call sort_dp(nkfold,norm,iperm,tol14)
1656 
1657  ! Loop over all k1 - k2
1658  opt_ng0(:)=0
1659  do i2=1,nk2
1660    ! This is used in case of screening calculation.
1661    ! If q is small treat it as zero. In this case, indeed,
1662    ! we use q=0 to calculate the oscillator matrix elements.
1663    if (is_zero(kbz2(:,i2),tolq0)) CYCLE
1664    do i1=1,nk1
1665      found=.FALSE.
1666 
1667      ! Separating in integer part and fractionary part
1668      k1mk2(:) = kbz1(:,i1)-kbz2(:,i2)
1669      ! Adding small tol to prevent 1 being in fractionary part
1670      kbigdiff(:) = FLOOR(k1mk2(:)+tol7)
1671      ksmalldiff(:) = k1mk2(:)-kbigdiff(:)
1672 
1673      call getkptnorm_bycomponent(ksmalldiff(:),factor,normdiff)
1674 
1675      ! Try to find the right smallkfold, corresponding to ksmalldiff
1676      ind = bisect(norm,normdiff)
1677 
1678      if (ind > 0) then
1679        if(ABS(norm(ind) - normdiff) < TOL_KDIFF) then
1680           found = .TRUE.
1681        end if
1682      end if
1683      if(ind < nkfold) then
1684        if(ABS(norm(ind+1) - normdiff) < TOL_KDIFF) then
1685           found = .TRUE.
1686           ind = ind + 1
1687        end if
1688      end if
1689 
1690      if (.not. found) then
1691        write(msg,'(a,2(2a,i4,3es16.8),a)')&
1692 &        'Not able to found umklapp G0 vector such as k1-k2 = kf+G0',ch10,&
1693 &        'point1 = ',i1,kbz1(:,i1),ch10,&
1694 &        'point2 = ',i2,kbz2(:,i2),ch10
1695        ABI_ERROR(msg)
1696      else
1697        ! We have found one k, extracting the max g0
1698        roundk(:) = ABS(kbigdiff(:) - kbigfold(:,iperm(ind)))
1699        opt_ng0(1) = MAX(opt_ng0(1),roundk(1))
1700        opt_ng0(2) = MAX(opt_ng0(2),roundk(2))
1701        opt_ng0(3) = MAX(opt_ng0(3),roundk(3))
1702      end if
1703    end do
1704  end do
1705 
1706 end subroutine get_ng0sh

m_bz_mesh/getkptnorm_bycomponent [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 getkptnorm_bycomponent

FUNCTION

  get the norm of one vector, by order of its components

INPUTS

  vect(3) = vector which should be evaluated
  factor = term which multiplies the components
    WARNING ! should be large enough to get unique order

OUTPUT

  norm = value of the norm

SOURCE

1728 subroutine getkptnorm_bycomponent(vect,factor,norm)
1729 
1730 !Arguments ------------------------------------
1731 !scalars
1732  integer,intent(in) :: factor
1733  real(dp),intent(out):: norm
1734 !arrays
1735  real(dp),intent(in) :: vect(3)
1736 !Local variables-------------------------------
1737 !scalars
1738  character(len=500) :: msg
1739 
1740 ! *************************************************************************
1741 
1742  ! Checking the factor is large enough
1743  !(skipping zero components, since in this case the product will be 0)
1744  if(ANY(vect(:)*factor < 1.0 .and. vect(:) > tol7)) then
1745     write(msg,'(a,a,a,a,a,a,a,a)') ' Not able to give unique norm to order vectors',ch10,&
1746 &       'This is likely related to a truncation error for a k-point in the input file',ch10,&
1747 &       'Always prefer fractional numbers in the input file instead of truncated ones',ch10,&
1748 &       '(e.g. 1/6 instead of 0.166666667)',ch10
1749     ABI_ERROR(msg)
1750  end if
1751 
1752  norm = (vect(1)*factor+vect(2))*factor+vect(3)
1753 
1754 end subroutine getkptnorm_bycomponent

m_bz_mesh/has_BZ_item [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 has_BZ_item

FUNCTION

  check if item belongs to the BZ  within a reciprocal lattice vector
  and return the index number and the reciprocal vector g0.

INPUTS

  Kmesh<kmesh_t>=datatype gathering information on the k-mesh
  item(3)=the k-point to be checked

OUTPUT

  .TRUE. if item is the BZ within a RL vector
  ikbz=Index of the k-point in the Kmesh%bz array
  g0(3)=Umklapp vector.

 FIXME
  Switch to routine version. Due to side-effects the present implementation
  might be source of bugs in logical statements

SOURCE

1120 logical function has_BZ_item(Kmesh, item, ikbz, g0)
1121 
1122 !Arguments ------------------------------------
1123 !scalars
1124  class(kmesh_t),intent(in) :: Kmesh
1125  integer,intent(out) :: ikbz
1126 !arrays
1127  integer,intent(out) :: g0(3)
1128  real(dp),intent(in) :: item(3)
1129 
1130 !Local variables-------------------------------
1131 !scalars
1132  integer :: ik_bz,yetfound
1133 !arrays
1134  integer :: g0_tmp(3)
1135 
1136 ! *************************************************************************
1137 
1138  has_BZ_item=.FALSE.; ikbz=0; g0=0; yetfound=0
1139  do ik_bz=1,Kmesh%nbz
1140    if (isamek(item,Kmesh%bz(:,ik_bz),g0_tmp)) then
1141      has_BZ_item=.TRUE.
1142      ikbz=ik_bz
1143      g0 = g0_tmp
1144      yetfound=yetfound+1
1145      !EXIT
1146    end if
1147  end do
1148 
1149  if (yetfound/=0.and.yetfound/=1) then
1150    ABI_ERROR('Multiple k-points found')
1151  end if
1152 
1153 end function has_BZ_item

m_bz_mesh/has_IBZ_item [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 has_IBZ_item

FUNCTION

  Check if item belongs to the IBZ within a reciprocal lattice vector

INPUTS

  Kmesh<kmesh_t>=Datatype gathering information on the mesh in the BZ.
  item(3)=the k-point to be checked

OUTPUT

  Return .TRUE. if item is the IBZ within a RL vector
  ikibz=The index of the k-point in the IBZ.
  g0(3)=The reciprocal lattice vector.

SOURCE

1176 logical function has_IBZ_item(Kmesh,item,ikibz,g0)
1177 
1178 !Arguments ------------------------------------
1179 !scalars
1180  class(kmesh_t),intent(in) :: Kmesh
1181  integer,intent(out) :: ikibz
1182 !arrays
1183  integer,intent(out) :: g0(3)
1184  real(dp),intent(in) :: item(3)
1185 
1186 !Local variables-------------------------------
1187 !scalars
1188  integer :: ik_ibz,yetfound
1189  !character(len=500) :: msg
1190 !arrays
1191  integer :: g0_tmp(3)
1192 
1193 ! *************************************************************************
1194 
1195  has_IBZ_item=.FALSE.; ikibz=0; g0=0; yetfound=0
1196  do ik_ibz=1,Kmesh%nibz
1197    if (isamek(item,Kmesh%ibz(:,ik_ibz),g0_tmp)) then
1198      has_IBZ_item=.TRUE.
1199      ikibz=ik_ibz
1200      g0 = g0_tmp
1201      yetfound=yetfound+1
1202      !EXIT
1203    end if
1204  end do
1205 
1206  if (yetfound/=0.and.yetfound/=1) then
1207    ABI_BUG("multiple k-points found")
1208  end if
1209 
1210 end function has_IBZ_item

m_bz_mesh/identk [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 identk

FUNCTION

 Identify k-points in the whole BZ starting from the IBZ.
 Generate also symmetry tables relating the BZ to the IBZ.

INPUTS

  kibz(3,nkibz)=Coordinates of k-points in the IBZ.
  nkibz=Number of k points in IBZ.
  nkbzmx=Maximum number of k points in BZ.
  nsym=Number of symmetry operations.
  timrev=2 if time reversal symmetry can be used; 1 otherwise.
  symrec(3,3,nsym)=Symmetry operation matrices in reciprocal space.
  symafm(nsym)=(anti)ferromagnetic part of symmetry operations.
  [ref_bz(:,:)]= Reference set of points in the full Brillouin zone.

OUTPUT

  kbz(3,nkbzmx)= k-points in whole BZ
  ktab(nkbzmx)= table giving for each k-point in the BZ (array kbz),
   the corresponding irreducible point in the array (kibz)
   k_BZ= (IS) kIBZ where S is one of the symrec operations and I is the inversion or the identity
    where k_BZ = (IS) k_IBZ and S = \transpose R^{-1}
  ktabi(nkbzmx)= for each k-point in the BZ defines whether inversion has to be
   considered in the relation k_BZ=(IS) k_IBZ (1 => only S; -1 => -S)
  ktabo(nkbzmx)= the symmetry operation S that takes k_IBZ to each k_BZ
  nkbz= no. of k-points in the whole BZ
  wtk(nkibz)= weight for each k-point in IBZ for symmetric quantities:
              no. of distinct ks in whole BZ/(timrev*nsym)

NOTES

  The logic of the routine relies on the assumption that kibz really represent an irreducible set.
  If symmetrical points are present in the input list, indeed, some the output weights will turn out to be zero.
  An initial check is done at the beginning of the routine to trap this possible error.

SOURCE

1416 subroutine identk(kibz,nkibz,nkbzmx,nsym,timrev,symrec,symafm,kbz,ktab,ktabi,ktabo,nkbz,wtk,ref_bz)
1417 
1418 !Arguments ------------------------------------
1419 !scalars
1420  integer,intent(in) :: nkbzmx,nkibz,nsym,timrev
1421  integer,intent(out) :: nkbz
1422 !arrays
1423  integer,intent(in) :: symafm(nsym),symrec(3,3,nsym)
1424  integer,intent(out) :: ktab(nkbzmx),ktabi(nkbzmx),ktabo(nkbzmx)
1425  real(dp),intent(in) :: kibz(3,nkibz)
1426  real(dp),intent(out) :: kbz(3,nkbzmx),wtk(nkibz)
1427  real(dp),optional,intent(in) :: ref_bz(:,:)
1428 
1429 !Local variables ------------------------------
1430 !scalars
1431  integer :: ik1,ik2,ikbz,ikibz,iold,isym,itim
1432  integer :: ikref,nkref,isym_swp,itim_swp,ikibz_swp
1433  logical :: is_irred_set
1434  logical :: found,ltest
1435  character(len=500) :: msg
1436 !arrays
1437  integer :: g0(3)
1438  real(dp) :: knew(3),k1(3),k2(3)
1439  real(dp) :: kref(3),kbz_swp(3)
1440 
1441 ! *************************************************************************
1442 
1443  DBG_ENTER("COLL")
1444  !
1445  ! === Check whether kibz really forms an irreducible set ===
1446  is_irred_set=.TRUE.
1447  do ik1=1,nkibz-1
1448    k1=kibz(:,ik1)
1449    do ik2=ik1+1,nkibz
1450      k2=kibz(:,ik2)
1451 
1452      do itim=1,timrev
1453        do isym=1,nsym
1454          if (symafm(isym)==-1) CYCLE
1455          knew = (3-2*itim) * MATMUL(symrec(:,:,isym),k2)
1456          if (isamek(k1,knew,g0)) then
1457            is_irred_set=.FALSE.
1458            write(msg,'(2(a,3f8.4),2(a,i2))')&
1459 &            ' k1 = ',k1,' is symmetrical of k2 = ',k2,' through sym = ',isym,' itim = ',itim
1460            ABI_WARNING(msg)
1461          end if
1462        end do
1463      end do
1464 
1465    end do
1466  end do
1467 
1468  !call klist_isirred(nkibz,kibz,Cryst,nimg)
1469 
1470  if (.not.is_irred_set) then
1471    ABI_WARNING("Input array kibz does not constitute an irreducible set.")
1472  end if
1473  !
1474  ! === Loop over k-points in IBZ ===
1475  ! * Start with zero no. of k-points found.
1476  nkbz=0
1477  do ikibz=1,nkibz
1478    wtk(ikibz) = zero
1479 
1480    ! === Loop over time-reversal I and symmetry operations S  ===
1481    ! * Use spatial inversion instead of time reversal whenever possible.
1482    do itim=1,timrev
1483      do isym=1,nsym
1484        if (symafm(isym)==-1) CYCLE
1485        !
1486        ! * Form IS k
1487        knew=(3-2*itim)*MATMUL(symrec(:,:,isym),kibz(:,ikibz))
1488        !
1489        ! * Check whether it has already been found (to within a RL vector).
1490        iold=0
1491        do ikbz=1,nkbz
1492          if (isamek(knew,kbz(:,ikbz),g0)) then
1493            iold=iold+1
1494            exit
1495          end if
1496        end do
1497        !
1498        ! * If not yet found add to kbz and increase the weight.
1499        if (iold==0) then
1500          nkbz=nkbz+1
1501          wtk(ikibz)=wtk(ikibz)+one
1502          if (nkbz>nkbzmx) then
1503            ABI_BUG(sjoin('nkbzmx too small, nkbzmx = ',itoa(nkbzmx),', increase nkbzmx !'))
1504          end if
1505          kbz(:,nkbz) = knew(:)
1506          ktab (nkbz) = ikibz
1507          ktabo(nkbz) = isym
1508          ktabi(nkbz) = 3-2*itim
1509        end if
1510        !
1511       end do
1512    end do
1513 
1514  end do !ikibz
1515 
1516  if (PRESENT(ref_bz)) then
1517    call wrtout(std_out," Pruning the k-points not in ref_bz then reordering tables","COLL")
1518 
1519    nkref = SIZE(ref_bz,DIM=2)
1520    ltest = (nkref>=nkbz.and.nkref<=nkbzmx)
1521    if (.not.ltest) then
1522      write(msg,'(3(a,i0))')" Wrong value for nkref: nkref= ",nkref," nkbz= ",nkbz," nkbzmx =",nkbzmx
1523      ABI_WARNING(msg)
1524    end if
1525 
1526    do ikref=1,nkref
1527      kref = ref_bz(:,ikref)
1528      found=.FALSE.
1529 
1530      do ikbz=1,nkbz ! Loop on the set of BZ points found above.
1531        if (isequalk(kref,kbz(:,ikbz))) then ! Swap indices.
1532          kbz_swp   = kbz(:,ikref)
1533          ikibz_swp = ktab (ikref)
1534          isym_swp  = ktabo(ikref)
1535          itim_swp  = ktabi(ikref)
1536 
1537          kbz(:,ikref) = kref
1538          ktab (ikref) = ktab (ikbz)
1539          ktabo(ikref) = ktabo(ikbz)
1540          ktabi(ikref) = ktabi(ikbz)
1541 
1542          kbz(:,ikbz) = kbz_swp
1543          ktab (ikbz) = ikibz_swp
1544          ktabo(ikbz) = isym_swp
1545          ktabi(ikbz) = itim_swp
1546 
1547          found=.TRUE.; EXIT
1548        end if
1549      end do
1550 
1551      if (.not.found) then
1552        write(msg,'(a,3es16.8)')" One of the k-point in ref_bz is not a symmetrical image of the IBZ: ",kref
1553        ABI_ERROR(msg)
1554      end if
1555    end do
1556    !
1557    ! Change nkbz to nkref, then get the new weights.
1558    nkbz=nkref; wtk=zero
1559    do ikref=1,nkref
1560      ikibz = ktab(ikref)
1561      wtk(ikibz) = wtk(ikibz) + 1
1562    end do
1563  end if ! PRESENT(ref_bz)
1564  !
1565  ! * Weights are normalized to 1.
1566  wtk = wtk/SUM(wtk)
1567 
1568  DBG_EXIT("COLL")
1569 
1570 end subroutine identk

m_bz_mesh/isamek [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 isamek

FUNCTION

 Test two k-points for equality.
 Return .TRUE. is they are equal within a reciprocal lattice vector G0.

INPUTS

  k1(3),k2(3)=The two k points to be compared.

OUTPUT

 Return .TRUE. if they are the same within a RL vector,
        .FALSE. if they are different.
 G0(3)=if .TRUE. G0(3) is the reciprocal lattice vector such as k1=k2+G0

SOURCE

1044 logical function isamek(k1, k2, g0)
1045 
1046 !Arguments ------------------------------------
1047 !arrays
1048  integer,intent(out) :: g0(3)
1049  real(dp),intent(in) :: k1(3),k2(3)
1050 
1051 ! *************************************************************************
1052 
1053  isamek = isinteger(k1-k2,TOL_KDIFF)
1054 
1055  if (isamek) then
1056    g0=NINT(k1-k2)
1057  else
1058    g0=HUGE(1)
1059  end if
1060 
1061 end function isamek

m_bz_mesh/isequalk [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 is_equalk

FUNCTION

 Return .TRUE. if two points are equal within a reciprocal lattice vector.

INPUTS

  q1(3),q2(3)=The two points to be compared for equivalence.

OUTPUT

SOURCE

1080 logical function isequalk(q1, q2)
1081 
1082 !Arguments ------------------------------------
1083  real(dp),intent(in) :: q1(3),q2(3)
1084 
1085 !Local variables-------------------------------
1086 !arrays
1087  integer :: g0(3)
1088 ! *************************************************************************
1089 
1090  isequalk = isamek(q1,q2,g0)
1091 
1092 end function isequalk

m_bz_mesh/kmesh_free [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 kmesh_free

FUNCTION

 Deallocate all dynamics entities present in a kmesh_t structure.

INPUTS

 Kmesh<kmesh_t>=The datatype to be freed.

SOURCE

560 subroutine kmesh_free(Kmesh)
561 
562 !Arguments ------------------------------------
563  class(kmesh_t),intent(inout) :: Kmesh
564 
565 ! *********************************************************************
566 
567  !@kmesh_t
568 !integer
569  ABI_SFREE(Kmesh%rottb)
570  ABI_SFREE(Kmesh%rottbm1)
571  ABI_SFREE(Kmesh%tab)
572  ABI_SFREE(Kmesh%tabi)
573  ABI_SFREE(Kmesh%tabo)
574  ABI_SFREE(Kmesh%umklp)
575 
576 !real
577  ABI_SFREE(Kmesh%ibz)
578  ABI_SFREE(Kmesh%bz)
579  ABI_SFREE(Kmesh%shift)
580  ABI_SFREE(Kmesh%wt)
581 
582 !complex
583  ABI_SFREE(Kmesh%tabp)
584 
585 end subroutine kmesh_free

m_bz_mesh/kmesh_init [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 kmesh_init

FUNCTION

  Initialize and construct a kmesh_t datatype
  gathering information on the mesh in the Brilloin zone.

INPUTS

  nkibz=Number of irreducible k-points.
  kibz(3,nkibz)=Irreducible k-points in reduced coordinates.
  Cryst<crystal_t> = Info on unit cell and its symmetries
     %nsym=number of symmetry operations
     %symrec(3,3,nsym)=symmetry operations in reciprocal space
     %tnons(3,nsym)=fractional translations
  kptopt=option for the generation of k points (see input variable description)
  [wrap_1zone]=If .TRUE., the points are wrapped in in the first BZ. Defaults to .FALSE. to preserve GW implementation.
  [ref_bz(:,:)]= Reference set of points in the full Brillouin zone used to prune k-points.

OUTPUT

  Kmesh<kmesh_t>=Datatype gathering information on the k point sampling.

SOURCE

402 subroutine kmesh_init(Kmesh,Cryst,nkibz,kibz,kptopt,wrap_1zone,ref_bz,break_symmetry)
403 
404 !Arguments ------------------------------------
405 !scalars
406  class(kmesh_t),intent(inout) :: Kmesh
407  integer,intent(in) :: nkibz,kptopt
408  logical,optional,intent(in) :: wrap_1zone,break_symmetry
409  type(crystal_t),intent(in) :: Cryst
410 !arrays
411  real(dp),intent(in) :: kibz(3,nkibz)
412  real(dp),optional,intent(in) :: ref_bz(:,:)
413 
414 !Local variables-------------------------------
415 !scalars
416  integer :: ik_bz,ik_ibz,isym,nkbz,nkbzX,nsym,timrev,itim
417  real(dp) :: shift1,shift2,shift3
418  logical :: ltest,do_wrap,do_hack
419 !arrays
420  integer,allocatable :: ktab(:),ktabi(:),ktabo(:)
421  real(dp) :: rm1t(3),kbz_wrap(3)
422  real(dp),allocatable :: kbz(:,:),wtk(:)
423 
424 ! *************************************************************************
425 
426  DBG_ENTER("COLL")
427 
428  !@kmesh_t
429  ! === Initial tests on input arguments ===
430  ltest=(Cryst%timrev==1.or.Cryst%timrev==2)
431  ABI_CHECK(ltest, sjoin('Wrong value for timrev= ', itoa(Cryst%timrev)))
432 
433  if (ALL(kptopt/=(/1,3/))) then
434    ABI_WARNING(sjoin("Not allowed value for kptopt: ", itoa(kptopt)))
435  end if
436 
437  Kmesh%kptopt = kptopt
438 
439  nsym   = Cryst%nsym
440  timrev = Cryst%timrev
441 
442  !
443  ! === Find BZ from IBZ and fill tables ===
444  nkbzX=nkibz*nsym*timrev ! Maximum possible number
445  ABI_MALLOC(kbz,(3,nkbzX))
446  ABI_MALLOC(wtk,(nkibz))
447  ABI_MALLOC(ktab,(nkbzX))
448  ABI_MALLOC(ktabi,(nkbzX))
449  ABI_MALLOC(ktabo,(nkbzX))
450 
451  if (PRESENT(ref_bz)) then
452    call identk(kibz,nkibz,nkbzX,nsym,timrev,cryst%symrec,cryst%symafm,kbz,ktab,ktabi,ktabo,nkbz,wtk,ref_bz=ref_bz)
453  else
454    call identk(kibz,nkibz,nkbzX,nsym,timrev,cryst%symrec,cryst%symafm,kbz,ktab,ktabi,ktabo,nkbz,wtk)
455  end if
456 
457  ! TODO: Force the k-points to be in the first Brillouin zone.
458  !  Now the GW tests seem to be OK, additional tests have to be done though.
459  do_wrap=.FALSE.; if (PRESENT(wrap_1zone)) do_wrap=wrap_1zone
460  !do_wrap=.TRUE.
461 
462  if (do_wrap) then ! Wrap the BZ points in the interval ]-1/2,1/2]
463    do ik_bz=1,nkbz
464      call wrap2_pmhalf(kbz(1,ik_bz),kbz_wrap(1),shift1)
465      call wrap2_pmhalf(kbz(2,ik_bz),kbz_wrap(2),shift2)
466      call wrap2_pmhalf(kbz(3,ik_bz),kbz_wrap(3),shift3)
467      kbz(:,ik_bz) = kbz_wrap
468    end do
469  end if
470  !
471  ! ================================================================
472  ! ==== Create data structure to store information on k-points ====
473  ! ================================================================
474  !
475  ! * Dimensions.
476  Kmesh%nbz   =nkbz      ! Number of points in the full BZ
477  Kmesh%nibz  =nkibz     ! Number of points in the IBZ
478  Kmesh%nsym  =nsym      ! Number of operations
479  Kmesh%timrev=timrev    ! 2 if time-reversal is used, 1 otherwise
480  !
481  ! * Arrays.
482  Kmesh%gmet   = Cryst%gmet
483  Kmesh%gprimd = Cryst%gprimd
484 
485  ABI_MALLOC(Kmesh%bz ,(3,nkbz))
486  Kmesh%bz   =  kbz(:,1:nkbz )  ! Red. coordinates of points in full BZ.
487  ABI_MALLOC(Kmesh%ibz,(3,nkibz))
488  Kmesh%ibz  = kibz(:,1:nkibz)  ! Red. coordinates of points in IBZ.
489 
490  ABI_MALLOC(Kmesh%tab ,(nkbz))
491  Kmesh%tab  = ktab (1:nkbz)    ! Index of the irred. point in the array IBZ.
492  ABI_MALLOC(Kmesh%tabi,(nkbz))
493  Kmesh%tabi = ktabi(1:nkbz)    !-1 if time reversal must be used to obtain this point,
494  ABI_MALLOC(Kmesh%tabo,(nkbz))
495  Kmesh%tabo = ktabo(1:nkbz)    ! Symm. operation that rotates k_IBZ onto \pm k_BZ
496                                                              ! (depending on tabi)
497  ABI_MALLOC(Kmesh%wt,(nkibz))
498  Kmesh%wt(:)= wtk(1:nkibz)     ! Weight for each k_IBZ
499 
500  ABI_MALLOC(Kmesh%rottbm1,(nkbz,timrev,nsym))
501  ABI_MALLOC(Kmesh%rottb  ,(nkbz,timrev,nsym))
502 
503  do_hack = .FALSE.
504  if (PRESENT(ref_bz) .and. PRESENT(break_symmetry)) then
505    do_hack = break_symmetry
506  end if
507 
508  if (do_hack) then
509    ABI_WARNING("Hacking the rottb tables!")
510    do ik_bz=1,nkbz
511      Kmesh%rottbm1(ik_bz,:,:) = ik_bz
512      Kmesh%rottb  (ik_bz,:,:) = ik_bz
513    end do
514  else
515    call setup_k_rotation(nsym,timrev,cryst%symrec,nkbz,Kmesh%bz,Cryst%gmet,Kmesh%rottb,Kmesh%rottbm1)
516  end if
517 
518  ! TODO umklp can be calculated inside setup_k_rotation.
519  ABI_MALLOC(Kmesh%umklp,(3,nkbz))
520  do ik_bz=1,nkbz
521    ik_ibz= Kmesh%tab (ik_bz)
522    isym  = Kmesh%tabo(ik_bz)
523    itim  = (3-Kmesh%tabi(ik_bz))/2
524    Kmesh%umklp(:,ik_bz) = NINT( -Kmesh%bz(:,ik_bz) + (3-2*itim)*MATMUL(cryst%symrec(:,:,isym),Kmesh%ibz(:,ik_ibz)) )
525  end do
526 
527  ABI_MALLOC(Kmesh%tabp,(nkbz))
528  do ik_bz=1,nkbz
529    isym  =Kmesh%tabo(ik_bz)
530    ik_ibz=Kmesh%tab (ik_bz)
531    rm1t=MATMUL(TRANSPOSE(cryst%symrec(:,:,isym)),cryst%tnons(:,isym))
532    Kmesh%tabp(ik_bz)=EXP(-(0.,1.)*two_pi*DOT_PRODUCT(kibz(:,ik_ibz),rm1t))
533  end do
534 
535  ABI_FREE(kbz)
536  ABI_FREE(wtk)
537  ABI_FREE(ktab)
538  ABI_FREE(ktabi)
539  ABI_FREE(ktabo)
540 
541  DBG_EXIT("COLL")
542 
543 end subroutine kmesh_init

m_bz_mesh/kmesh_print [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 kmesh_print

FUNCTION

 Print the content of a kmesh_t datatype

INPUTS

 Kmesh<kmesh_t>=the datatype to be printed
 [header]=optional header
 [unit]=the unit number for output
 [prtvol]=verbosity level
 [mode_paral]=either "COLL" or "PERS"

OUTPUT

  Only printing.

SOURCE

609 subroutine kmesh_print(Kmesh,header,unit,prtvol,mode_paral)
610 
611 !Arguments ------------------------------------
612 !scalars
613  class(kmesh_t),intent(in) :: Kmesh
614  integer,optional,intent(in) :: prtvol,unit
615  character(len=4),optional,intent(in) :: mode_paral
616  character(len=*),optional,intent(in) :: header
617 
618 !Local variables-------------------------------
619 !scalars
620  integer,parameter :: nmaxk=50
621  integer :: ii,ik,my_unt,my_prtvol
622  character(len=100) :: fmt
623  character(len=4) :: my_mode
624  character(len=500) :: msg
625 
626 ! *************************************************************************
627 
628  my_unt =std_out; if (PRESENT(unit      )) my_unt   =unit
629  my_prtvol=0    ; if (PRESENT(prtvol    )) my_prtvol=prtvol
630  my_mode='COLL' ; if (PRESENT(mode_paral)) my_mode  =mode_paral
631 
632  msg=' ==== Info on the Kmesh% object ==== '
633  if (PRESENT(header)) msg=' ==== '//TRIM(ADJUSTL(header))//' ==== '
634  call wrtout(my_unt,msg,my_mode)
635 
636  write(msg,'(a,i5,3a)')&
637   ' Number of points in the irreducible wedge : ',Kmesh%nibz,ch10,&
638   ' Reduced coordinates and weights : ',ch10
639  call wrtout(my_unt,msg,my_mode)
640 
641  write(fmt,*)'(1x,i5,a,2x,3es16.8,3x,f11.5)'
642  do ik=1,Kmesh%nibz ! Add tol8 for portability reasons.
643    write(msg,fmt) ik,') ',(Kmesh%ibz(ii,ik),ii=1,3),Kmesh%wt(ik)+tol8
644    call wrtout(my_unt,msg,my_mode)
645  end do
646 
647  SELECT CASE (Kmesh%timrev)
648  CASE (1)
649    write(msg,'(2a,i2,3a,i5,a)')ch10,&
650     ' Together with ',Kmesh%nsym,' symmetry operations (time-reversal symmetry not used) ',ch10,&
651     ' yields ',Kmesh%nbz,' points in the full Brillouin Zone.'
652 
653  CASE (2)
654    write(msg,'(2a,i2,3a,i5,a)')ch10,&
655     ' Together with ',Kmesh%nsym,' symmetry operations and time-reversal symmetry ',ch10,&
656     ' yields ',Kmesh%nbz,' points in the full Brillouin Zone.'
657 
658  CASE DEFAULT
659    ABI_BUG(sjoin('Wrong value for timrev:', itoa(Kmesh%timrev)))
660  END SELECT
661 
662  call wrtout(my_unt,msg,my_mode)
663 
664  if (my_prtvol > 0) then
665    write(fmt,*)'(1x,i5,a,2x,3es16.8)'
666    do ik=1,Kmesh%nbz
667      if (my_prtvol==1 .and. ik>nmaxk) then
668        write(msg,'(a)')' prtvol=1, do not print more points.'
669        call wrtout(my_unt,msg,my_mode); EXIT
670      end if
671      write(msg,fmt)ik,') ',(Kmesh%bz(ii,ik),ii=1,3)
672      call wrtout(my_unt,msg,my_mode)
673    end do
674  end if
675 
676  ! Additional printing
677  if (my_prtvol >= 10) then
678    write(msg,'(2a)')ch10,&
679    '                  Full point  ------->    Irred point -->            through:  Symrec  Time-Rev (1=No,-1=Yes) G0(1:3) '
680    call wrtout(my_unt,msg,my_mode)
681    write(fmt,*)'(2x,i5,2x,2(3(f7.4,2x)),i3,2x,i2,3(i3))'
682    do ik=1,Kmesh%nbz
683      write(msg,fmt)ik,Kmesh%bz(:,ik),Kmesh%ibz(:,Kmesh%tab(ik)),Kmesh%tabo(ik),Kmesh%tabi(ik),Kmesh%umklp(:,ik)
684      call wrtout(my_unt,msg,my_mode)
685    end do
686  end if
687 
688  write(msg,'(a)')ch10
689  call wrtout(my_unt,msg,my_mode)
690 
691 end subroutine kmesh_print

m_bz_mesh/kmesh_t [ Types ]

[ Top ] [ m_bz_mesh ] [ Types ]

NAME

 kmesh_t

FUNCTION

 The kmesh_t structured datatype contains different information on the grid used to sample the BZ :
 the k-points in the full Brillouin zone BZ, the irreducible wedge IBZ as well as tables describing
 the symmetry relationship between the points.

SOURCE

 80  type,public :: kmesh_t
 81 
 82   !scalars
 83   integer :: nshift = 0
 84 
 85   integer :: nbz = 0
 86   ! Number of points in the BZ.
 87 
 88   integer :: nibz = 0
 89   ! Number of points in the IBZ.
 90 
 91   integer :: nsym
 92   ! Number of symmetry operations.
 93 
 94   integer :: kptopt
 95   ! kptopt=option for the generation of k points (see input variable description)
 96   !
 97   ! 1  if both time-reversal and point group symmetries are used.
 98   ! 2  if only time-reversal symmetry is used.
 99   ! 3  do not take into account any symmetry (except the identity).
100   ! 4  if time-reversal is not used (spin-orbit coupling).
101   ! <0 number of segments used to construct the k-path for NSCF calculation.
102 
103   integer :: timrev
104   ! 2 if time reversal symmetry can be used, 1 otherwise.
105 
106  !arrays
107   integer :: kptrlatt(3,3) = NONE_KPTRLATT
108    ! Coordinates of three vectors in real space, expressed in reduced coordinates.
109    ! They define a super-lattice in real space. The k point lattice is the reciprocal of
110    ! this super-lattice, eventually shifted by shift.
111    ! Not available if the structure is initialized from the points in the IBZ.
112 
113   integer,allocatable :: rottb(:,:,:)
114   ! rottb(nbz,timrev,nsym),
115   ! Index of (IS)k in the BZ array where S is a sym operation in reciprocal space,
116   ! I is the identity or the inversion operator (1,2 resp)
117 
118   integer,allocatable :: rottbm1(:,:,:)
119   ! rottbm1(nbz,timrev,nsym)
120   ! Index of IS^{-1} k in the BZ array.
121 
122   integer,allocatable :: tab(:)
123   ! tab(nbz)
124   ! For each point in the BZ, it gives the index of the symmetric irreducible point in the array ibz.
125 
126   integer,allocatable :: tabi(:)
127   ! tabi(nbz)
128   ! For each point in the BZ, tabi tells whether time-reversal has to be
129   ! used to obtain k_BZ starting from the corresponding point in the IBZ  (1=>no, -1=>yes)
130 
131   integer,allocatable :: tabo(:)
132   ! tabo(nbz)
133   ! For each point in the BZ, it gives the index in the array symrec of the
134   ! symmetry operation in reciprocal space which rotates k_IBZ onto \pm k_BZ (depending on tabi)
135 
136   integer,allocatable :: umklp(:,:)
137    ! umklp(3,nbz)
138    ! The Umklapp G0-vector such as kbz + G0 = (IS) k_ibz, where kbz is in the first BZ.
139 
140   real(dp) :: gmet(3,3)
141   ! Reciprocal space metric ($\textrm{bohr}^{-2}$).
142 
143   real(dp) :: gprimd(3,3)
144   ! Dimensional primitive translations for reciprocal space ($\textrm{bohr}^{-1}$)
145 
146   real(dp),allocatable :: bz(:,:)
147   ! bz(3,nbz)
148   ! Points in the BZ in reduced coordinates.
149   ! TODO should packed in shells.
150 
151   real(dp),allocatable :: ibz(:,:)
152   ! ibz(3,nibz)
153   ! Points in the IBZ in reduced coordinates.
154 
155   real(dp),allocatable :: shift(:,:)
156   !  shift(3,nshift)
157   !  Shift for k-points, not available is nshift=0. Usually nshift=1
158 
159   real(dp),allocatable :: wt(:)
160   ! wt(nibz)
161   ! Weights for each point in the IBZ.
162 
163   !%real(dp),allocatable :: vbox(:)
164   ! vbox(nkbz)
165   ! Volume of the small box centered on the k-point in the full BZ.
166   ! Mainly used for inhomogeneous meshes.
167 
168   complex(dpc),allocatable :: tabp(:)
169   ! tabp(nkbz)
170   ! For each point in the BZ, this table gives the phase factors associated
171   ! to non-symmorphic operations, i.e., e^{-i2\pi k_IBZ.R{^-1}t}=e^{-i2\pi k_BZ cdot t}
172   ! where \transpose R{-1}=S and  (S k_IBZ)=\pm k_BZ (depending on tabi)
173 
174  contains
175 
176    ! Methods
177    procedure :: init => kmesh_init            ! Main creation method.
178    procedure :: free => kmesh_free            ! Free memory
179    procedure :: print => kmesh_print          ! Printout of basic info on the object.
180    procedure :: get_bz_item => get_bz_item    ! Get point in the BZ and other useful quantities.
181    procedure :: get_ibz_item => get_IBZ_item  ! Get point in the IBZ and other useful quantities.
182    procedure :: get_bz_diff => get_BZ_diff    ! Get the difference k1-k2 in the BZ (if any).
183 
184 
185    procedure :: has_bz_item => has_BZ_item    ! Check if a point belongs to the BZ mesh.
186    procedure :: has_ibz_item => has_IBZ_item  ! Check if a point is in the IBZ
187    procedure :: isirred => bz_mesh_isirred    ! TRUE if ik_bz is in the IBZ (a non-zero umklapp is not allowed)
188 
189  end type kmesh_t
190 
191  public :: make_mesh             ! Initialize the mesh starting from kptrlatt and shift.
192  public :: find_qmesh            ! Find the Q-mesh defined as the set of all possible k1-k2 differences.
193 
194  public :: isamek                ! Check whether two points are equal within an umklapp G0.
195  public :: isequalk              ! Check whether two points are equal within an umklapp G0 (does not report G0)
196  public :: findqg0               ! Identify q + G0 = k1-k2.
197  public :: findq                 ! Helper routine returning the list of q-points.
198  public :: findnq                ! Helper routine returning the number of q-points.
199  public :: identk                ! Find the BZ starting from the irreducible k-points.
200  public :: get_ng0sh             ! Calculate the smallest box in RSpace able to treat all possible umklapp processes.
201  public :: box_len               ! Return the length of the vector connecting the origin with one the faces of the unit cell.

m_bz_mesh/kpath_free [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 kpath_free

FUNCTION

  Free memory allocated in the object

SOURCE

2864 subroutine kpath_free(Kpath)
2865 
2866 !Arguments ------------------------------------
2867 !scalars
2868  class(kpath_t),intent(inout) :: Kpath
2869 
2870 ! *************************************************************************
2871 
2872  ABI_SFREE(Kpath%ndivs)
2873  ABI_SFREE(Kpath%bounds2kpt)
2874  ABI_SFREE(Kpath%bounds)
2875  ABI_SFREE(Kpath%points)
2876  ABI_SFREE(Kpath%dl)
2877 
2878 end subroutine kpath_free

m_bz_mesh/kpath_new [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 kpath_new

FUNCTION

  Create a normalized path given the extrema.

INPUTS

  bounds(3,nbounds)=The points defining the path in reduced coordinates.
  gprimd(3,3)=Reciprocal lattice vectors
  ndivsm=Number of divisions to be used for the smallest segment.
   A negative value activates a specialized mode if with bounds is suppose to supply the full list of k-points.

SOURCE

2798 type(kpath_t) function kpath_new(bounds, gprimd, ndivsm) result(kpath)
2799 
2800 !Arguments ------------------------------------
2801 !scalars
2802  integer,intent(in) :: ndivsm
2803 !!arrays
2804  real(dp),intent(in) :: bounds(:,:),gprimd(3,3)
2805 
2806 !Local variables-------------------------------
2807  integer :: ii
2808 !arrays
2809  real(dp) :: dk(3)
2810 
2811 ! *************************************************************************
2812 
2813  ABI_CHECK(size(bounds, dim=1) == 3, "Wrong dim1 in bounds")
2814  !ABI_CHECK(ndivsm > 0, sjoin("ndivsm:", itoa(ndivsm)))
2815  Kpath%nbounds = size(bounds, dim=2)
2816  Kpath%ndivsm = ndivsm
2817 
2818  ! Compute reciprocal space metric.
2819  Kpath%gprimd = gprimd; Kpath%gmet = matmul(transpose(gprimd), gprimd)
2820 
2821  ABI_MALLOC(Kpath%ndivs, (Kpath%nbounds-1))
2822 
2823  if (kpath%ndivsm > 0) then
2824    call make_path(Kpath%nbounds, bounds, Kpath%gmet, "G", ndivsm, Kpath%ndivs, Kpath%npts, kpath%points, unit=dev_null)
2825  else
2826    ! Get list of points directly.
2827    kpath%ndivs = 1
2828    kpath%npts = kpath%nbounds
2829    ABI_MALLOC(Kpath%points, (3, Kpath%npts))
2830    kpath%points = bounds
2831  end if
2832 
2833  ABI_MALLOC(Kpath%bounds, (3, Kpath%nbounds))
2834  Kpath%bounds = bounds
2835 
2836  ! Compute distance between point i-1 and i
2837  ABI_CALLOC(kpath%dl, (kpath%npts))
2838  do ii=2,kpath%npts
2839    dk = kpath%points(:, ii-1) - kpath%points(:,ii)
2840    kpath%dl(ii) = normv(dk, kpath%gmet, "G")
2841  end do
2842 
2843  ! Mapping bounds --> points
2844  ABI_MALLOC(kpath%bounds2kpt, (kpath%nbounds))
2845  kpath%bounds2kpt(1) = 1
2846  do ii=1,kpath%nbounds-1
2847    kpath%bounds2kpt(ii+1) = sum(kpath%ndivs(:ii)) + 1
2848  end do
2849 
2850 end function kpath_new

m_bz_mesh/kpath_print [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 kpath_print

FUNCTION

  Print info on the path.

INPUTS

  [unit]=Unit number for output. Defaults to std_out
  [prtvol]=Verbosity level.
  [header]=String to be printed as header for additional info.
  [pre]=Optional string prepended to output e.g. #. Default: " "

OUTPUT

  Only printing

SOURCE

2901 subroutine kpath_print(kpath, header, unit, prtvol, pre)
2902 
2903 !Arguments ------------------------------------
2904 !scalars
2905  integer,optional,intent(in) :: unit,prtvol
2906  character(len=*),optional,intent(in) :: header,pre
2907  class(kpath_t),intent(in) :: kpath
2908 
2909 !Local variables-------------------------------
2910  integer :: unt,my_prtvol,ii
2911  character(len=500) :: my_pre
2912 
2913 ! *************************************************************************
2914 
2915  unt = std_out; if (present(unit)) unt = unit
2916  my_prtvol = 0; if (present(prtvol)) my_prtvol = prtvol
2917  my_pre = " "; if (present(pre)) my_pre = pre
2918  if (unt <= 0) return
2919 
2920  if (present(header)) write(unt,"(a)") sjoin(my_pre, '==== '//trim(adjustl(header))//' ==== ')
2921  write(unt, "(a)") sjoin(my_pre, " Number of points:", itoa(kpath%npts), ", ndivsmall:", itoa(kpath%ndivsm))
2922  write(unt, "(a)") sjoin(my_pre, " Boundaries and corresponding index in the k-points array:")
2923  do ii=1,kpath%nbounds
2924    write(unt, "(a)") sjoin(my_pre, itoa(kpath%bounds2kpt(ii)), ktoa(kpath%bounds(:,ii)))
2925  end do
2926  write(unt, "(a)") sjoin(my_pre, " ")
2927 
2928  if (my_prtvol > 10) then
2929    do ii=1,kpath%npts
2930      write(unt, "(a)") sjoin(my_pre, ktoa(kpath%points(:,ii)))
2931    end do
2932  end if
2933 
2934 end subroutine kpath_print

m_bz_mesh/kpath_t [ Types ]

[ Top ] [ m_bz_mesh ] [ Types ]

NAME

 path_t

FUNCTION

  A (normalized) path in reciprocal space

SOURCE

215  type,public :: kpath_t
216 
217   integer :: nbounds = 0
218     ! Number of extrema defining the path.
219 
220   integer :: ndivsm = 0
221     ! Number of divisions used to sample the smallest segment.
222 
223   integer :: npts = 0
224     ! Total number of points in the path.
225 
226   real(dp) :: gprimd(3,3)
227    ! Reciprocal lattice vectors.
228 
229   real(dp) :: gmet(3,3)
230    ! Metric matrix in G-space.
231 
232   integer,allocatable :: ndivs(:)
233    ! ndivs(nbounds-1)
234    ! Number of divisions for each segment.
235 
236   integer,allocatable :: bounds2kpt(:)
237    ! bounds2kpt(nbounds)
238    ! bounds2kpt(i): Index of the i-th extrema in the pts(:) array.
239 
240   real(dp),allocatable :: bounds(:,:)
241     ! bounds(3,nbounds)
242     ! The points defining the path in reduced coordinates.
243 
244   real(dp),allocatable :: points(:,:)
245     ! points(3,npts)
246     ! The points of the path in reduced coordinates.
247 
248   real(dp),allocatable :: dl(:)
249     ! dl(npts)
250     ! dl(i) = Distance between the (i-1)-th and the i-th k-point. dl(1) = zero
251 
252  contains
253 
254   procedure :: free => kpath_free
255    ! Free memory
256 
257   procedure :: print => kpath_print
258    ! Print the path.
259 
260  end type kpath_t
261 
262  public :: kpath_new        ! Construct a new path
263  !public :: kpath_from_cryst ! High-level API to construct a path from a crystal_t
264  public :: make_path        ! Construct a normalized path. TODO: Remove

m_bz_mesh/littlegroup_free_0D [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 littlegroup_free_0D

FUNCTION

  Deallocate all associated pointers defined in the littlegroup_t data type.

INPUTS

   Ltg=datatype to be freed

OUTPUT

SOURCE

2571 subroutine littlegroup_free_0D(Ltg)
2572 
2573 !Arguments ------------------------------------
2574  class(littlegroup_t),intent(inout) :: Ltg
2575 
2576 ! *********************************************************************
2577 
2578  !@littlegroup_t
2579  ABI_SFREE(Ltg%g0)
2580  ABI_SFREE(Ltg%ibzq)
2581  ABI_SFREE(Ltg%bz2ibz)
2582  ABI_SFREE(Ltg%ibz2bz)
2583  ABI_SFREE(Ltg%igmG0)
2584  ABI_SFREE(Ltg%flag_umklp)
2585  ABI_SFREE(Ltg%preserve)
2586  ABI_SFREE(Ltg%tab)
2587  ABI_SFREE(Ltg%tabo)
2588  ABI_SFREE(Ltg%tabi)
2589  ABI_SFREE(Ltg%wtksym)
2590 
2591 end subroutine littlegroup_free_0D

m_bz_mesh/littlegroup_free_1D [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 littlegroup_free_1D

FUNCTION

  Deallocate all the associated pointers defined in the littlegroup_t data type.

INPUTS

   Ltg=datatype to be freed

OUTPUT

SOURCE

2610 subroutine littlegroup_free_1D(Ltg)
2611 
2612 !Arguments ------------------------------------
2613  class(littlegroup_t),intent(inout) :: Ltg(:)
2614 
2615 !Local variables-------------------------------
2616  integer :: ipt
2617 
2618 ! *********************************************************************
2619 
2620  do ipt=1,SIZE(Ltg)
2621    call littlegroup_free_0D(Ltg(ipt))
2622  end do
2623 
2624 end subroutine littlegroup_free_1D

m_bz_mesh/littlegroup_init [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 littlegroup_init

FUNCTION

 Finds symmetry operations belonging to the little group associated to an external
 point ext_pt and fills symmetry tables.

INPUTS

 ext_pt(3)= External point in the Brillouin zone in reduce coordinated
 nbz=number of points in the full BZ.
 bz(3,nbz)=points in the full BZ.
 Cryst<crystal_t>= Info on symmetries and unit cell.
 use_umklp=flag to include umklapp G0 vectors in the definition of the little group (0:n0,1:yes)
 npwe=If greater than 0, the index of G-Go in the gvec(:,1:npwvec) array will be calculated
  and stored in %igmG0 for each symmetry preserving the external q. Note that G is one of the npwe vectors.
 gvec(3,npwe) coordinates of G vectors
 [timrev]=Optional argument to change the value of time-reversal. If not given, the value from cryst is used.

SOURCE

2253 subroutine littlegroup_init(Ltg, ext_pt, nbz, bz, Cryst, use_umklp, npwe, gvec, timrev)
2254 
2255 !Arguments ------------------------------------
2256 !scalars
2257  class(littlegroup_t),intent(inout) :: Ltg
2258  integer,intent(in) :: nbz, npwe, use_umklp
2259  type(crystal_t),target,intent(in) :: Cryst
2260  real(dp),intent(in) :: bz(3, nbz)
2261 !arrays
2262  integer,optional,intent(in) :: gvec(:,:) ! (3,npwe)
2263  real(dp),intent(in) :: ext_pt(3)
2264  integer,optional,intent(in) :: timrev
2265 
2266 !Local variables-------------------------------
2267 !scalars
2268  integer :: dummy_timrev,enough,idx,ige,igpw,ik,ind,iold,iout,isym,itest,itim
2269  integer :: nkibzq,nsym,nsym_Ltg,ntest,my_timrev,ierr,npwvec
2270  real(dp) :: G0len,kin,mG0len,max_kin
2271  logical :: found,found_identity,use_antiferro
2272  character(len=500) :: msg
2273 !arrays
2274  integer :: g0(3),gg(3),gmG0(3),identity(3,3),nop(Cryst%timrev),nopg0(2)
2275  integer :: symxpt(4,2,Cryst%nsym)
2276  integer,allocatable :: indkpt1(:),symafm_ltg(:),symrec_Ltg(:,:,:),bz2ibz_smap(:,:)
2277  integer,pointer :: symafm(:),symrec(:,:,:)
2278  real(dp) :: knew(3)
2279  real(dp),allocatable :: ktest(:,:),wtk(:),wtk_folded(:)
2280 
2281 !************************************************************************
2282 
2283  ABI_CHECK(any(cryst%timrev == [1, 2]), sjoin("Wrong value for cryst%timrev:", itoa(cryst%timrev)))
2284 
2285  ! Destroy structure if it already exists
2286  call Ltg%free()
2287 
2288  ! Copy useful data.
2289  nsym          =  Cryst%nsym
2290  my_timrev     =  Cryst%timrev
2291  if (present(timrev)) then
2292    my_timrev = timrev
2293    ABI_CHECK_ILEQ(my_timrev, cryst%timrev, "my_timrev cannot be greater that cryst%timrev")
2294  end if
2295 
2296  symrec        => Cryst%symrec
2297  symafm        => Cryst%symafm
2298  use_antiferro =  Cryst%use_antiferro
2299 
2300  ! Store dimensions and useful info.
2301  Ltg%nsym_sg  = nsym
2302  Ltg%timrev   = my_timrev
2303  Ltg%nbz      = nbz
2304  !Ltg%use_umklp=use_umklp ! 1 if umklapp processes are used
2305  Ltg%ext_pt(:)=ext_pt(:)
2306 
2307  ABI_MALLOC(Ltg%G0, (3,2,nsym))
2308  ABI_MALLOC(Ltg%ibzq, (nbz))
2309  ABI_MALLOC(Ltg%bz2ibz, (nbz))
2310  ABI_MALLOC(Ltg%preserve, (2, nsym))
2311  ABI_MALLOC(Ltg%wtksym, (2, nsym, nbz))
2312  ABI_MALLOC(Ltg%tab, (nbz))
2313  ABI_MALLOC(Ltg%tabi, (nbz))
2314  ABI_MALLOC(Ltg%tabo, (nbz))
2315  ABI_MALLOC(Ltg%flag_umklp, (2, nsym))
2316 
2317  ! In the old GW implementation we were removing symmetries related by time-reversal and
2318  ! sometimes it happened that only the inversion was reported in the KSS file (see outkss.F90).
2319  identity(:,:)=RESHAPE((/1,0,0,0,1,0,0,0,1/),(/3,3/)) ; found_identity=.FALSE.
2320  do isym=1,nsym
2321    if (ALL(symrec(:,:,isym) == identity)) then
2322     found_identity=.TRUE.; EXIT
2323    end if
2324  end do
2325  if (.not. found_identity) then
2326    write(msg,'(5a)')&
2327      'Only the inversion was found in the set of symmetries read from the KSS file ',ch10,&
2328      'Likely you are using a KSS file generated with an old version of Abinit, ',ch10,&
2329      'To run a GW calculation with an old KSS file, use version < 5.5 '
2330    ABI_ERROR(msg)
2331  end if
2332 
2333  ! Find operations in the little group as well as umklapp vectors G0
2334  call littlegroup_q(nsym, ext_pt, symxpt, symrec, symafm, dummy_timrev, prtvol=0)
2335 
2336  Ltg%preserve(:,:)=0; Ltg%g0(:,:,:)=0; Ltg%flag_umklp(:,:)=0; mG0len=zero
2337 
2338  do itim=1,my_timrev
2339    do isym=1,nsym
2340      if (symafm(isym)==-1) CYCLE
2341 
2342      if (symxpt(4, itim, isym) == 1) then  !\pm Sq = q+g0
2343        if (ANY(symxpt(1:3, itim, isym) /= 0) .and. use_umklp == 0) CYCLE ! Exclude non zero G0 vectors
2344        Ltg%preserve(itim, isym) = 1
2345        g0(:)=symxpt(1:3, itim, isym); Ltg%g0(:, itim, isym) = g0(:)
2346        if (ANY(Ltg%g0(:, itim, isym) /= 0)) Ltg%flag_umklp(itim, isym) = 1
2347        ! Max radius to be considered to include all G0s
2348        G0len = normv(g0,Cryst%gmet,'G')
2349        mG0len = MAX(mG0len, G0len)
2350      end if
2351    end do
2352  end do
2353 
2354  nop(:) = 0; nopg0(:) = 0
2355  do itim=1,my_timrev
2356    nop  (itim) = SUM(Ltg%preserve  (itim,:))
2357    nopg0(itim) = SUM(Ltg%flag_umklp(itim,:))
2358  end do
2359  nsym_Ltg = SUM(nop(:))
2360 
2361  ! Store little group operations, include time-reversal if present.
2362  Ltg%nsym_Ltg = nsym_Ltg
2363  ABI_MALLOC(symrec_Ltg, (3, 3, Ltg%nsym_Ltg))
2364 
2365  ind = 1
2366  do itim=1,my_timrev
2367    do isym=1,nsym
2368      if (Ltg%preserve(itim,isym)==1) then
2369       if (itim==1) symrec_Ltg(:,:,ind) = symrec(:,:,isym)
2370       if (itim==2) symrec_Ltg(:,:,ind) =-symrec(:,:,isym)
2371       ind = ind+1
2372      end if
2373    end do
2374  end do
2375 
2376  ! Check the closure of the (ferromagnetic) little group
2377  ABI_MALLOC(symafm_ltg,(Ltg%nsym_Ltg))
2378  symafm_ltg(:) = 1
2379  call sg_multable(Ltg%nsym_Ltg,symafm_ltg,symrec_Ltg,ierr)
2380  ABI_CHECK(ierr == 0, "Error in group closure")
2381 
2382  ABI_FREE(symafm_ltg)
2383 
2384  ! Find the irreducible zone associated to ext_pt
2385  ! Do not use time-reversal since it has been manually introduced previously
2386  ABI_MALLOC(indkpt1, (nbz))
2387  ABI_MALLOC(wtk_folded, (nbz))
2388  ABI_MALLOC(wtk, (nbz))
2389  ABI_MALLOC(bz2ibz_smap, (6, nbz))
2390  wtk=one; iout=0; dummy_timrev=0
2391 
2392  call symkpt(0,Cryst%gmet,indkpt1,iout, bz, nbz, nkibzq, Ltg%nsym_Ltg, symrec_Ltg, dummy_timrev, wtk, wtk_folded, &
2393              bz2ibz_smap, xmpi_comm_self)
2394 
2395  ABI_FREE(bz2ibz_smap)
2396  ABI_FREE(indkpt1)
2397  ABI_FREE(wtk)
2398 
2399  Ltg%nibz_Ltg = nkibzq
2400  !
2401  ! === Set up table in the BZ ===
2402  ! * 0 if the point does not belong to IBZ_xpt, 1 otherwise
2403  ABI_MALLOC(Ltg%ibz2bz,(nkibzq))
2404  Ltg%ibzq(:)=0; Ltg%bz2ibz(:)=0; Ltg%ibz2bz(:)=0
2405 
2406  ind=0; enough=0
2407  do ik=1,nbz
2408    if (wtk_folded(ik)>tol8) then
2409      ind = ind + 1
2410      Ltg%ibzq(ik) = 1
2411      Ltg%bz2ibz(ik) = ind
2412      Ltg%ibz2bz(ind)= ik
2413    end if
2414  end do
2415  ABI_CHECK_IEQ(ind, Ltg%nibz_Ltg, "BUG: ind /= Ltg%nibz_Ltg")
2416 
2417  ! Reconstruct full BZ starting from IBZ_q.
2418  ! Calculate appropriate weight for each item (point,symmetry operation,time-reversal)
2419  Ltg%tab=0; Ltg%tabo=0; Ltg%tabi=0; Ltg%wtksym(:,:,:)=0
2420 
2421  ! Start with zero no. of k-points found
2422  ntest = 0
2423  ABI_MALLOC(ktest, (3, nbz))
2424  ktest = zero
2425 
2426  do ik=1,nbz
2427    if (Ltg%ibzq(ik) /= 1) CYCLE
2428    ! * Loop over symmetry operations S and time-reversal.
2429    ! * Use spatial inversion instead of time reversal whenever possible.
2430    do itim=1,my_timrev
2431      do isym=1,nsym
2432 
2433       ! Form IS k only for (IS) pairs in the (ferromagnetic) little group.
2434       if (symafm(isym)==-1) CYCLE
2435       if (Ltg%preserve(itim,isym)==0) CYCLE
2436       knew(:)=(3-2*itim)*MATMUL(symrec(:,:,isym), bz(:,ik))
2437       !
2438       ! Check whether it has already been found (to within a RL vector)
2439       iold=0
2440       do itest=1,ntest
2441         if (isamek(knew(:),ktest(:,itest),gg)) iold=iold+1
2442       end do
2443 
2444       if (iold==0) then
2445         ! Found new BZ point
2446         ! For this point the operation (isym,itim) must be considered to reconstruct the full BZ
2447         Ltg%wtksym(itim,isym,ik)=1
2448         ntest=ntest+1
2449         ktest(:,ntest)=knew(:)
2450         !
2451         ! Now find knew in the BZ array
2452         found=.FALSE.
2453         do idx=1,nbz
2454           if (isamek(knew(:), bz(:,idx), gg)) then ! They are the same within a RL vector
2455             Ltg%tab (idx)=ik
2456             Ltg%tabo(idx)=isym
2457             Ltg%tabi(idx)=3-2*itim
2458             found=.TRUE.; EXIT
2459           end if
2460         end do
2461         if (.not.found) then
2462           write(msg,'(a,3f12.6,a)')'Not able to find the ',knew(:),' in the array BZ '
2463           ABI_ERROR(msg)
2464         end if
2465       end if
2466 
2467      end do !isym
2468    end do !itim
2469 
2470  end do !nbz
2471 
2472  ABI_FREE(ktest)
2473 
2474  if (ntest/=nbz) then
2475    ABI_BUG(sjoin('ntest - nbz = ',itoa(ntest-nbz)))
2476  end if
2477 
2478  if (sum(Ltg%wtksym) /= nbz) then
2479    ABI_BUG(sjoin('sum(Ltg%wtksym)-nbz = ', itoa(SUM(Ltg%wtksym)-nbz)))
2480  end if
2481 
2482  Ltg%max_kin_gmG0=zero
2483 
2484  if (npwe > 0.and. PRESENT(gvec)) then
2485    npwvec = SIZE(gvec,DIM=2)
2486    ! This correspond to the case in which we need to know the index of G-Go in the gvec array
2487    ! where G is one of the npwe vectors. This is required in screening but not in sigma.
2488    ! The drawback is that the effective G sphere used to calculate the oscillators must be smaller
2489    ! that gvec if we want to avoid possible aliasing effects. Lifting this constraint would require
2490    ! a lot of boring coding. (no need to do this if ext_pt=zero, but oh well)
2491    ABI_MALLOC(Ltg%igmG0,(npwe,2,nsym))
2492    Ltg%igmG0(:,:,:)=0
2493    max_kin=zero
2494 
2495    ! Loop over symmetry operations S and time-reversal
2496    do itim=1,my_timrev
2497      do isym=1,nsym
2498        ! Form IS k only for (IS) pairs in the little group
2499        if (symafm(isym)==-1) CYCLE
2500        if (Ltg%preserve(itim,isym)/=0) then
2501          g0(:)=Ltg%g0(:,itim,isym)
2502          do ige=1,npwe
2503            gmG0(:)=gvec(:,ige)-g0(:)
2504            kin=half*normv(gmG0,Cryst%gmet,'G')**2
2505            max_kin=MAX(max_kin,kin)
2506 
2507            found=.FALSE.
2508            do igpw=1,npwvec
2509              if (ALL(gvec(:,igpw)-gmG0(:)==0)) then
2510                Ltg%igmG0(ige,itim,isym)=igpw
2511                found=.TRUE.; EXIT
2512              end if
2513            end do
2514            if (.not. found) then
2515              write(msg,'(5a,f8.3,2a,3i5)')&
2516               'Not able to found G-G0 in the largest G-spere ',ch10,&
2517               'Decrease the size of epsilon or, if possible, increase ecutwfn (>ecuteps) ',ch10,&
2518               'Minimum required cutoff energy for G-G0 sphere= ',kin,ch10,&
2519               'G0 = ',g0(:)
2520              ABI_ERROR(msg)
2521            end if
2522          end do
2523        end if
2524      end do
2525    end do
2526    Ltg%max_kin_gmG0=max_kin
2527  end if
2528  ABI_FREE(symrec_Ltg)
2529 
2530  ! DEBUG SECTION
2531  !do ik=1,nbz
2532  !  if (ABS(SUM(Ltg%wtksym(1,:,ik)+Ltg%wtksym(2,:,ik))-wtk_folded(ik))>tol6) then
2533  !    write(std_out,*)' sum(Ltg%wtksym,ik)-wtk_folded(ik) = ',sum(Ltg%wtksym(1,:,ik)+Ltg%wtksym(2,:,ik))-wtk_folded(ik)
2534  !    write(std_out,*)Ltg%wtksym(1,:,ik),Ltg%wtksym(2,:,ik),wtk_folded(ik)
2535  !    write(std_out,*)ik, bz(:,ik)
2536  !    ABI_BUG("Wrong weight")
2537  !  end if
2538  !end do
2539  !do ik=1,nbz
2540  !  knew = Ltg%tabi(ik) * MATMUL(symrec(:,:,Ltg%tabo(ik)), bz(:,Ltg%tab(ik)))
2541  !  if (.not.isamek(knew, bz(:,ik),gg)) then
2542  !    write(std_out,*)knew, bz(:,ik)
2543  !    write(std_out,*)Ltg%tabo(ik),Ltg%tabi(ik),Ltg%tab(ik)
2544  !    ABI_BUG("Wrong tables")
2545  !  end if
2546  !end do
2547 
2548  ABI_FREE(wtk_folded)
2549 
2550  DBG_EXIT("COLL")
2551 
2552 end subroutine littlegroup_init

m_bz_mesh/littlegroup_print [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 littlegroup_print

FUNCTION

  Print info on the littlegroup_t data type.

INPUTS

  Ltg=the datatype to be printed
  [unit]=the unit number for output
  [prtvol]=verbosity level
  [mode_paral]=either "COLL" or "PERS"

OUTPUT

  Only printing

SOURCE

2647 subroutine littlegroup_print(Ltg, unit, prtvol, mode_paral)
2648 
2649 !Arguments ------------------------------------
2650  class(littlegroup_t),intent(in) :: Ltg
2651  integer,optional,intent(in) :: prtvol,unit
2652  character(len=4),optional,intent(in) :: mode_paral
2653 
2654 !Local variables-------------------------------
2655 !scalars
2656  integer :: itim,my_unt,my_prtvol
2657  character(len=4) :: my_mode
2658  character(len=500) :: msg
2659 !arrays
2660  integer :: nop(Ltg%timrev),nopg0(Ltg%timrev)
2661 
2662 ! *********************************************************************
2663 
2664  my_unt   =std_out; if (PRESENT(unit      )) my_unt   =unit
2665  my_prtvol=0      ; if (PRESENT(prtvol    )) my_prtvol=prtvol
2666  my_mode  ='COLL' ; if (PRESENT(mode_paral)) my_mode  =mode_paral
2667 
2668  write(msg,'(7a,i0,a,i0,2a,i0,a,i0)')ch10, &
2669   ' ==== Little Group Info ==== ', ch10, &
2670   '  External point: ',trim(ktoa(Ltg%ext_pt)), ch10, &
2671   '  Number of points in the IBZ defined by little group:  ', Ltg%nibz_Ltg, '/', Ltg%nbz,ch10, &
2672   '  Number of operations in the little group: ',Ltg%nsym_Ltg,'/',Ltg%nsym_sg
2673  call wrtout(my_unt,msg,my_mode)
2674 
2675  nop=0 ; nopg0=0
2676  do itim=1,Ltg%timrev
2677    nop  (itim)=SUM(Ltg%preserve  (itim,:))
2678    nopg0(itim)=SUM(Ltg%flag_umklp(itim,:))
2679  end do
2680 
2681  do itim=1,Ltg%timrev
2682    if (itim==1) then
2683      write(msg,'(2(a,i2,a))') &
2684        '  No time-reversal symmetry with zero umklapp: ',nop(1)-nopg0(1),ch10,&
2685        '  No time-reversal symmetry with non-zero umklapp: ',nopg0(1),ch10
2686      call wrtout(my_unt,msg,my_mode)
2687    else if (itim==2) then
2688      write(msg,'(2(a,i2,a))') &
2689        '  time-reversal symmetry with zero umklapp: ',nop(2)-nopg0(2),ch10,&
2690        '  time-reversal symmetry with non-zero umklapp: ',nopg0(2),ch10
2691      call wrtout(my_unt,msg,my_mode)
2692    end if
2693  end do
2694 
2695 end subroutine littlegroup_print

m_bz_mesh/littlegroup_t [ Types ]

[ Top ] [ m_bz_mesh ] [ Types ]

NAME

 littlegroup_t

FUNCTION

 For the GW part of ABINIT. The littlegroup_t structured datatype gather information on
 the little group associated to an external vector q. The little group associated to q
 is defined as the subset of the space group that preserves q, modulo a G0 vector
 (also called umklapp vector). Namely

  Sq = q +G0,  where S is an operation in reciprocal space.

 If time reversal symmetry holds true, it is possible to enlarge the little group by
 including the operations such as
  -Sq = q+ G0.

 The operations belongin to the little group define an irriducible wedge in the Brillouin zone
 that is, usually, larger than the irredubile zone defined by the space group.
 The two zone coincide when q=0

TODO

 Rationalize most of the arrays, in particular the tables
 This structure shoud be rewritten almost from scratch, thus avoid using it
 for your developments.

SOURCE

296  type,public :: littlegroup_t
297 
298   integer :: npw             ! No. of planewaves used to describe the wavefuntion, used to dimension igmG0
299   integer :: nsym_sg         ! No. of operations in the space group (*NOT* the little group)
300   integer :: nsym_ltg        ! No. of symmetry operations in the little group (time-reversal is included, if can be used)
301   integer :: timrev          ! 2 if time-reversal is considered, 1 otherwise
302   integer :: nbz             ! No. of kpoints in the full BZ
303   integer :: nibz_ltg        ! No. of points in the irreducible wedge defined by the little group
304   !integer :: use_umklp      ! 1 if umklapp processes are included
305 
306   real(dp) :: max_kin_gmG0
307   ! Max kinetic energy of G-G0 in case of umklapp.
308 
309   integer,allocatable :: G0(:,:,:)
310   ! (3,2,nsym_sg)
311   ! Reduced coordinates of the umklapp G0 vector.
312 
313   integer,allocatable :: ibzq(:)
314   ! ibzq(nbz)
315   ! 1 if the point belongs to the IBZ_q defined by ext_pt, 0 otherwise.
316 
317   integer,allocatable :: bz2ibz(:)
318   ! bz2ibz(nbz)
319   ! Index of the point in the irreducible wedge defined by the little group, 0 otherwise.
320 
321   integer,allocatable :: ibz2bz(:)
322   ! ibz2bz(nibz_ltg)
323   ! The correspondind index in the BZ array
324 
325   integer,allocatable :: igmG0(:,:,:)
326   ! iumklp(npw,2,nsym_sg)
327   ! Index of G-G0 in the FFT array for each operations IS (I=\pm 1).
328 
329   integer,allocatable :: flag_umklp(:,:)
330   ! flag_umklp(2,nsym_sg)
331   ! 1 if the operation IS requires a non null G0 vector to preserve q, 0 otherwise.
332 
333   integer,allocatable :: preserve(:,:)
334   ! preserve(2, nsym_sg)
335   ! (1,S) is 1 if the operation S in rec space preserves the external q-point i.e Sq=q+G0
336   ! (2,S) is 1 if -Sq=q+G0. G0 is a reciprocal lattice vector also called "umklapp vector".
337 
338   integer,allocatable :: tab(:)
339   ! tab(nbz)
340   ! For each point in BZ, the index of the irreducible point (kIBZ_q) in the irreducible
341   ! wedge defined by the little group of q. kBZ= (IS) kIBZ where I is the inversion or the identity.
342 
343   integer,allocatable :: tabo(:)
344   ! tabo(nbz)
345   ! The index of the operation S in the little group that rotates kIBZ_q into \pm kBZ.
346 
347   integer,allocatable :: tabi(:)
348   ! tabi(nbz)
349   ! for each k-point in the BZ defines whether inversion has to be
350   ! considered in the relation kBZ= IS kIBZ_q (1 => only S; -1 => -S).
351 
352   integer,allocatable :: wtksym(:,:,:)
353   ! (2, nsym_sg, kbz)
354   ! 1 if IS belongs to the little group, 0 otherwise TODO (should invert the first two dimensions)
355 
356   real(dp) :: ext_pt(3)
357   ! The external point defining the little group.
358 
359  contains
360 
361    procedure :: init => littlegroup_init
362    procedure :: print => littlegroup_print
363    procedure :: free => littlegroup_free_0D
364 
365  end type littlegroup_t
366 
367  public :: littlegroup_free

m_bz_mesh/make_mesh [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 make_mesh

FUNCTION

 Initialize the kmesh_t starting from kptrlatt and shiftk

INPUTS

 Cryst<crystal_t>=Info on the crystalline structure.
 nshiftk=Number of shifts for the mesh.
 kptrlatt(3,3)= Coordinates of three vectors in real space, expressed in reduced coordinates.
  They define a super-lattice in real space. The k point lattice is the reciprocal of
  this super-lattice, eventually shifted by shift.
 shiftk(3,nshiftk)=Shifts for the k-mesh.
 [vacuum(3)]=For each direction, 0 if no vacuum, 1 if vacuum

OUTPUT

 Kmesh<kmesh_t>=Object gathering info on the sampling of the Brillouin zone.

SOURCE

1275 subroutine make_mesh(Kmesh,Cryst,kptopt,kptrlatt,nshiftk,shiftk,&
1276 &  vacuum,break_symmetry)  ! Optional
1277 
1278 !Arguments -------------------------------
1279 !scalars
1280  integer,intent(in) :: nshiftk,kptopt
1281  logical,optional,intent(in) :: break_symmetry
1282  type(kmesh_t),intent(inout) :: Kmesh
1283  type(crystal_t),intent(in) :: Cryst
1284 !arrays
1285  integer,intent(inout) :: kptrlatt(3,3)
1286  integer,optional,intent(in) :: vacuum(3)
1287  real(dp),intent(in) :: shiftk(3,nshiftk)
1288 
1289 !Local variables -------------------------
1290 !scalars
1291  integer,parameter :: chksymbreak0=0
1292  integer :: iscf,nkbz,nkibz,nkpt_computed,my_nshiftk
1293  real(dp) :: kptrlen
1294  logical :: my_break_symmetry
1295 !arrays
1296  integer :: my_vacuum(3)
1297  real(dp),allocatable :: kibz(:,:),wtk(:),my_shiftk(:,:),ref_kbz(:,:)
1298 
1299 ! *************************************************************************
1300 
1301  DBG_ENTER("COLL")
1302 
1303  !@kmesh_t
1304  !if (ALL(kptopt/=(/1,2,3,4/))) then
1305  if (ALL(kptopt/=(/1,3/))) then
1306    ABI_WARNING(sjoin(" Not allowed value for kptopt: ", itoa(kptopt)))
1307  end if
1308  !
1309  ! ======================================================================
1310  ! ==== First call to getkgrid to obtain nkibz as well as the BZ set ====
1311  ! ======================================================================
1312  iscf=7  ! use for the Weights in NSCF calculation. check it more carefully.
1313  nkibz=0 ! Compute number of k-points in the BZ and IBZ
1314 
1315  my_vacuum = (/0,0,0/); if (PRESENT(vacuum)) my_vacuum=vacuum
1316 
1317  my_nshiftk = nshiftk
1318  ABI_CHECK(my_nshiftk>0.and.my_nshiftk<=MAX_NSHIFTK, sjoin("Wrong nshiftk must be between 1 and ", itoa(MAX_NSHIFTK)))
1319  ABI_MALLOC(my_shiftk, (3, MAX_NSHIFTK))
1320  my_shiftk=zero; my_shiftk(:,1:nshiftk) = shiftk(:,:)
1321 
1322  !write(std_out,*)" In make_mesh"
1323  !write(std_out,*)" kptopt   ",kptopt," kptrlatt ",kptrlatt
1324  !write(std_out,*)" nshiftk  ",nshiftk," shiftk   ",shiftk
1325 
1326  ABI_MALLOC(kibz,(3,nkibz))
1327  ABI_MALLOC(wtk,(nkibz))
1328 
1329  call getkgrid(chksymbreak0,0,iscf,kibz,kptopt,kptrlatt,kptrlen,Cryst%nsym,0,nkibz,my_nshiftk,&
1330 &  Cryst%nsym,Cryst%rprimd,my_shiftk,Cryst%symafm,Cryst%symrel,my_vacuum,wtk,fullbz=ref_kbz)
1331 
1332  nkbz = SIZE(ref_kbz,DIM=2)
1333 
1334  ABI_FREE(kibz)
1335  ABI_FREE(wtk)
1336 
1337  !write(std_out,*)" after getkgrid1: nkbz = ",nkbz," nkibz=",nkibz
1338  !write(std_out,*)" ref_kbz = ",ref_kbz
1339 
1340  ! ==============================================================
1341  ! ==== Recall getkgrid to get kibz(3,nkibz) and wtk(nkibz) =====
1342  ! ==============================================================
1343 
1344  ABI_MALLOC(kibz,(3,nkibz))
1345  ABI_MALLOC(wtk,(nkibz))
1346 
1347  call getkgrid(chksymbreak0,0,iscf,kibz,kptopt,kptrlatt,kptrlen,Cryst%nsym,nkibz,nkpt_computed,my_nshiftk,&
1348 &  Cryst%nsym,Cryst%rprimd,my_shiftk,Cryst%symafm,Cryst%symrel,my_vacuum,wtk)
1349 
1350  ! Store quantities that cannot be easily (and safely) calculated if we only know the IBZ.
1351  Kmesh%nshift   = my_nshiftk
1352  Kmesh%kptrlatt = kptrlatt
1353 
1354  ! Call the main creation method to get the tables tabo, tabi, tabp, umklp...
1355  ! kmesh_init will reconstruct the BZ from kibz but pruning the k-points not in ref_bz
1356  ! TODO: solve problem with timrev
1357  my_break_symmetry=.FALSE.; if (PRESENT(break_symmetry)) my_break_symmetry=break_symmetry
1358  call kmesh_init(Kmesh,Cryst,nkibz,kibz,kptopt,ref_bz=ref_kbz,break_symmetry=my_break_symmetry)
1359 
1360  ABI_FREE(ref_kbz)
1361  ABI_FREE(kibz)
1362  ABI_FREE(wtk)
1363 
1364  ABI_MALLOC(Kmesh%shift,(3,my_nshiftk))
1365  Kmesh%shift=my_shiftk(:,1:my_nshiftk)
1366  ! Init Kmesh is breaking nshiftk
1367  Kmesh%nshift=my_nshiftk
1368 
1369  ABI_FREE(my_shiftk)
1370 
1371  DBG_EXIT("COLL")
1372 
1373 end subroutine make_mesh

m_bz_mesh/make_path [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 make_path

FUNCTION

  Generate a normalized path given the extrema.
  See also kpath_t and kpath_new (recommended API).

INPUTS

  nbounds=Number of extrema defining the path.
  bounds(3,nbounds)=The points defining the path in reduced coordinates.
  met(3,3)=Metric matrix.
  space='R' for real space, G for reciprocal space.
  ndivsm=Number of divisions to be used for the smallest segment.
  [unit]=Fortran unit for formatted output. Default: dev_null

OUTPUT

  npts=Total number of points in the normalized circuit.
  ndivs(nbounds-1)=Number of division for each segment
  path: allocated inside the routine. When the subroutine returns, path(3,npts) will
    contain the path in reduced coordinates.

SOURCE

1783 subroutine make_path(nbounds, bounds, met, space, ndivsm, ndivs, npts, path, unit)
1784 
1785 !Arguments ------------------------------------
1786 !scalars
1787  integer,intent(in) :: nbounds,ndivsm
1788  integer,optional,intent(in) :: unit
1789  integer,intent(out) :: npts
1790  character(len=1),intent(in) :: space
1791 !arrays
1792  integer,intent(out) :: ndivs(nbounds-1)
1793  real(dp),intent(in) :: bounds(3,nbounds),met(3,3)
1794  real(dp),allocatable,intent(out) :: path(:,:)
1795 
1796 !Local variables-------------------------------
1797 !scalars
1798  integer,parameter :: prtvol=0
1799  integer :: idx,ii,jp,ount
1800  real(dp) :: nfact
1801  character(len=500) :: msg
1802 !arrays
1803  real(dp) :: diff(3),lng(nbounds-1)
1804 
1805 ! *************************************************************************
1806 
1807  ABI_CHECK(ndivsm > 0, sjoin('ndivsm', itoa(ndivsm)))
1808 
1809  ount = dev_null; if (present(unit)) ount = unit
1810 
1811  do ii=1,nbounds-1
1812    diff(:)=bounds(:,ii+1)-bounds(:,ii)
1813    lng(ii) = normv(diff,met,space)
1814  end do
1815 
1816  ! Avoid division by zero if any k(:,i+1)=k(:,i).
1817  nfact=MINVAL(lng)
1818  if (ABS(nfact)<tol6) then
1819    write(msg,'(3a)')&
1820      'Found two equivalent consecutive points in the path ',ch10,&
1821      'This is not allowed, modify the path in your input file'
1822    ABI_ERROR(msg)
1823  end if
1824 
1825  nfact=nfact/ndivsm
1826  ndivs(:)=NINT(lng(:)/nfact)
1827  npts=SUM(ndivs)+1 !1 for the first point
1828 
1829  write(msg,'(2a,i0,2a)')ch10,&
1830   ' Total number of points in the path: ',npts,ch10,&
1831   ' Number of divisions for each segment of the normalized path: '
1832  call wrtout(ount,msg)
1833 
1834  do ii=1,nbounds-1
1835    write(msg,'(2(3f8.5,a),i0,a)')bounds(:,ii),' ==> ',bounds(:,ii+1),' ( ndivs : ',ndivs(ii),' )'
1836    call wrtout(ount,msg)
1837  end do
1838  call wrtout(ount,ch10)
1839 
1840  ! Allocate and construct the path.
1841  ABI_MALLOC(path,(3,npts))
1842 
1843  if (prtvol > 0) call wrtout(ount,' Normalized Path: ')
1844  idx=0
1845  do ii=1,nbounds-1
1846    do jp=1,ndivs(ii)
1847      idx=idx+1
1848      path(:,idx)=bounds(:,ii)+(jp-1)*(bounds(:,ii+1)-bounds(:,ii))/ndivs(ii)
1849      if (prtvol > 0) then
1850        write(msg,'(i4,4x,3(f8.5,1x))')idx,path(:,idx)
1851        call wrtout(ount,msg)
1852      end if
1853    end do
1854  end do
1855  path(:,npts)=bounds(:,nbounds)
1856 
1857  if (prtvol > 0) then
1858    write(msg,'(i0,4x,3(f8.5,1x))')npts,path(:,npts)
1859    call wrtout(ount,msg)
1860  end if
1861 
1862 end subroutine make_path

m_bz_mesh/setup_k_rotation [ Functions ]

[ Top ] [ m_bz_mesh ] [ Functions ]

NAME

 setup_k_rotation

FUNCTION

 Set up tables giving the correspondence btw a k-point and its rotated image.

INPUTS

 timrev=2 if time-reversal can be used, 1 otherwise.
 nsym=Number of symmetry operations
 symrec(3,3,nsym)=Symmetry operations in reciprocal space in reduced coordinates.
 nbz=Number of k-points
 kbz(3,nbz)=k-points in reduced coordinates.
 gmet(3,3)=Metric in reciprocal space.

OUTPUT

 krottb(k,I,S)=Index of (IS) k in the array bz
 krottbm1(k,I,S)=Index of IS^{-1} k

SOURCE

717 subroutine setup_k_rotation(nsym,timrev,symrec,nbz,kbz,gmet,krottb,krottbm1)
718 
719 !Arguments ------------------------------------
720 !scalars
721  integer,intent(in) :: nbz,nsym,timrev
722 !arrays
723  integer,intent(in) :: symrec(3,3,nsym)
724  integer,intent(out) :: krottb(nbz,timrev,nsym),krottbm1(nbz,timrev,nsym)
725  real(dp),intent(in) :: kbz(3,nbz),gmet(3,3)
726 
727 !Local variables ------------------------------
728 !scalars
729  integer :: ik,ikp,isym,itim,nsh,ik_st !,sh_start
730  real(dp),parameter :: KTOL=tol6
731  real(dp) :: norm_old,norm !,norm_rot !norm_base
732  logical :: found,isok
733  character(len=500) :: msg
734 !arrays
735  integer :: g0(3)
736  integer :: iperm(nbz),shlim(nbz+1)
737  real(dp) :: shift(3),kbase(3),krot(3),knorm(nbz),kwrap(3),shlen(nbz+1)
738 
739 !************************************************************************
740 
741  DBG_ENTER("COLL")
742 
743  ! Sort the k-points according to their norm to speed up the search below.
744  do ik=1,nbz
745    call wrap2_pmhalf(kbz(1,ik),kwrap(1),shift(1))
746    call wrap2_pmhalf(kbz(2,ik),kwrap(2),shift(2))
747    call wrap2_pmhalf(kbz(3,ik),kwrap(3),shift(3))
748    knorm(ik) = normv(kwrap,gmet,"G")
749    iperm(ik)= ik
750  end do
751 
752  call sort_dp(nbz,knorm,iperm,KTOL)
753  !
754  ! The index of the initial (sorted) k-point in each shell
755  nsh=1; norm_old=knorm(1)
756 
757  shlim(1)=1; shlen(1) = norm_old
758  do ik_st=2,nbz
759    norm = knorm(ik_st)
760    if (ABS(norm-norm_old) > KTOL) then
761      norm_old   = norm
762      nsh        = nsh+1
763      shlim(nsh) = ik_st
764      shlen(nsh) = norm
765    end if
766  end do
767  shlim(nsh+1)=nbz+1
768  shlen(nsh+1)=HUGE(one)
769  !
770  ! === Set up k-rotation tables ===
771  ! * Use spatial inversion instead of time reversal whenever possible.
772  !call wrtout(std_out," Begin sorting ","COLL")
773 
774  isok=.TRUE.
775  do ik=1,nbz
776    kbase(:)=kbz(:,ik)
777    !
778    do itim=1,timrev
779      do isym=1,nsym
780        krot(:)=(3-2*itim)*MATMUL(symrec(:,:,isym),kbase)
781 
782        found=.FALSE.
783 #if 1
784       ! Old code
785        do ikp=1,nbz
786          if (isamek(krot,kbz(:,ikp),g0)) then
787            found=.TRUE.
788            krottb  (ik ,itim,isym)=ikp
789            krottbm1(ikp,itim,isym)=ik
790            EXIT
791          end if
792        end do
793 #else
794        !
795        ! Locate the shell index with bisection.
796        call wrap2_pmhalf(krot(1),kwrap(1),shift(1))
797        call wrap2_pmhalf(krot(2),kwrap(2),shift(2))
798        call wrap2_pmhalf(krot(3),kwrap(3),shift(3))
799        norm_rot = normv(kwrap,gmet,"G")
800        sh_start = bisect(shlen(1:nsh+1),norm_rot)
801 
802        do ik_st=shlim(sh_start),nbz
803          ikp = iperm(ik_st)
804          if (isamek(krot,kbz(:,ikp),g0)) then
805            found=.TRUE.
806            krottb  (ik ,itim,isym)=ikp
807            krottbm1(ikp,itim,isym)=ik
808            !write(std_out,*)ik_st,shlim(sh_start),nbz
809            EXIT
810          end if
811        end do
812 #endif
813        if (.not.found) then
814          isok=.FALSE.
815          !write(std_out,*)" norm_base,norm_rot ",norm_base,norm_rot
816          !write(std_out,*)normv(kbase,gmet,"G"),normv(krot,gmet,"G")
817          write(msg,'(2(a,i4),2x,2(3f12.6,2a),i3,a,i2)')&
818 &          'Initial k-point ',ik,'/',nbz,kbase(:),ch10,&
819 &          'Rotated k-point (not found) ',krot(:),ch10,&
820 &          'Through symmetry operation ',isym,' and itim ',itim
821          ABI_ERROR(msg)
822        end if
823 
824      end do
825    end do
826  end do
827 
828  if (.not.isok) then
829    ABI_ERROR('k-mesh not closed')
830  end if
831 
832  DBG_EXIT("COLL")
833 
834 end subroutine setup_k_rotation