LCOV - code coverage report
Current view: top level - src/56_recipspace - m_nesting.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 82.5 % 120 99
Test Date: 2026-09-19 17:42:43 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !!****m* ABINIT/m_nesting
       2              : !! NAME
       3              : !!  m_nesting
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides functions to compute the nesting factor:
       7              : !!      N(\qq) = \sum_{mn\kk} \delta(\ee_{\kpq m}) \delta(\ee_{\kk n})
       8              : !!
       9              : !! COPYRIGHT
      10              : !! Copyright (C) 2008-2026 ABINIT group (MG, MJV)
      11              : !! This file is distributed under the terms of the
      12              : !! GNU General Public License, see ~abinit/COPYING
      13              : !! or http://www.gnu.org/copyleft/gpl.txt .
      14              : !!
      15              : !! SOURCE
      16              : 
      17              : #if defined HAVE_CONFIG_H
      18              : #include "config.h"
      19              : #endif
      20              : 
      21              : #include "abi_common.h"
      22              : 
      23              : module m_nesting
      24              : 
      25              :  use defs_basis
      26              :  use m_errors
      27              :  use m_abicore
      28              :  use m_krank
      29              :  use m_sort
      30              : 
      31              :  use m_numeric_tools,  only : wrap2_zero_one, interpol3d_0d
      32              :  use m_io_tools,       only : open_file
      33              :  use m_bz_mesh,        only : make_path
      34              :  use m_pptools,        only : printxsf
      35              : 
      36              :  implicit none
      37              : 
      38              :  private
      39              : 
      40              :  public :: bfactor
      41              :  public :: mknesting
      42              :  public :: outnesting
      43              : !!***
      44              : 
      45              : !----------------------------------------------------------------------
      46              : 
      47              : CONTAINS  !=============================================================================
      48              : !!***
      49              : 
      50              : !!****f* m_nesting/bfactor
      51              : !! NAME
      52              : !! bfactor
      53              : !!
      54              : !! FUNCTION
      55              : !! Calculate the nesting factor
      56              : !!
      57              : !! INPUTS
      58              : !!  nkptfull = number of k-points in full grid
      59              : !!  kptfull(3,nkptfull) = k-point grid
      60              : !!  nqpt = number of qpoints
      61              : !!  qpt(3,nqpt) = q-point grid (must be a subgrid of the k grid),
      62              : !!                the nesting factor will be calculated for each q point in this array
      63              : !!  nkpt = eventually reduced number of k-points
      64              : !!  weight(nband,nkpt) =  integration weights for each k-point and band (NOT NORMALISED!!!)
      65              : !!  nband = number of bands
      66              : !!
      67              : !! OUTPUT
      68              : !!  nestfactor(nqpt) = array containing the nesting factor values
      69              : !!
      70              : !! NOTES
      71              : !! Inspired to nmsq_gam_sumfs and mkqptequiv
      72              : !!  TODO : better use of symmetries to reduce the computational effort
      73              : !! Must be called with kpt = full grid! Reduction by symmetry is not possible for q-dependent quantities (or not easy :)
      74              : !!
      75              : !! SOURCE
      76              : 
      77           23 : subroutine bfactor(nkptfull,kptfull,nqpt,qpt,krank,nkpt,weight,nband,nestfactor)
      78              : 
      79              : !Arguments ------------------------------------
      80              : !scalars
      81              :  integer,intent(in) :: nband,nkptfull,nqpt,nkpt
      82              : !arrays
      83              :  real(dp),intent(in) :: kptfull(3,nkptfull),qpt(3,nqpt),weight(nband,nkpt)
      84              :  real(dp),intent(out) :: nestfactor(nqpt)
      85              :  type(krank_t), intent(in) :: krank
      86              : 
      87              : !Local variables-------------------------------
      88              : !scalars
      89              :  integer :: ib1,ib2,ikplusq_irr,ikpt
      90              :  integer :: irank_kpt,ikpt_irr,iqpt,symrank_kpt
      91              :  real(dp) :: w1,w2
      92              :  !character(len=500) :: msg
      93              : !arrays
      94              :  real(dp) :: kptpq(3)
      95              : ! *************************************************************************
      96              : 
      97         1056 :  nestfactor(:)=zero
      98              : 
      99         1056 :  do iqpt=1,nqpt
     100       364944 :    do ikpt=1,nkptfull
     101       363888 :      irank_kpt = krank%get_rank(kptfull(:,ikpt))
     102       363888 :      ikpt_irr = krank%invrank(irank_kpt)
     103              : 
     104      1455552 :      kptpq(:) = kptfull(:,ikpt) + qpt(:,iqpt)
     105       363888 :      symrank_kpt = krank%get_rank(kptpq)
     106              : 
     107       363888 :      ikplusq_irr = krank%invrank(symrank_kpt)
     108       363888 :      if (ikplusq_irr == -1) then
     109            0 :        ABI_ERROR('It looks like no kpoint equiv to k+q!')
     110              :      end if
     111              : 
     112      2286441 :      do ib1=1,nband
     113      1921520 :        w1 = weight(ib1, ikpt_irr) ! weight for distance from the Fermi surface
     114      1921520 :        if (w1 < tol6 ) cycle
     115      3912420 :        do ib2=1,nband
     116      2973720 :          w2 = weight(ib2, ikplusq_irr) ! weight for distance from the Fermi surface
     117              :          if (w1 < tol6 ) cycle
     118      4895240 :          nestfactor(iqpt) = nestfactor(iqpt) + w1 * w2
     119              :        end do !ib2
     120              :      end do !ib1
     121              : 
     122              :    end do !ikpt
     123              :  end do !iqpt
     124              : 
     125              :  ! need prefactor of (1/nkptfull) for normalisation of integration
     126         1056 :  nestfactor(:) = (one/nkptfull) * nestfactor(:)
     127              : 
     128           23 : end subroutine bfactor
     129              : !!***
     130              : 
     131              : !----------------------------------------------------------------------
     132              : 
     133              : !!****f* m_nesting/mknesting
     134              : !! NAME
     135              : !! mknesting
     136              : !!
     137              : !! FUNCTION
     138              : !!  Calculate the nesting factor over the dense k-grid, interpolate the values along a given q path
     139              : !!  and write the data on file in the X-Y format or in the XCrysden format (XSF)
     140              : !!
     141              : !! INPUTS
     142              : !!  nkpt = number of k points
     143              : !!  kpt(3,nkpt) = k points
     144              : !!  nkx, nky, nkz = number of k-point along each direction
     145              : !!  nband = number of bands to be considered in the calculation
     146              : !!  weight(nband,nkpt) =  integration weights for each k-point and band
     147              : !!  nqpath = number of points requested along the trajectory
     148              : !!  qpath_vertices = vertices of the reciprocal space trajectory
     149              : !!  base_name = prefix of the output file
     150              : !!  gprimd(3,3) dimensional reciprocal lattice vectors
     151              : !!  gmet = metric in reciprocal space
     152              : !!  prtnest = flags governing the format of the output file
     153              : !!
     154              : !! OUTPUT
     155              : !!   Write data to file.
     156              : !!
     157              : !! SOURCE
     158              : 
     159            4 : subroutine mknesting(nkpt,kpt,kptrlatt,nband,weight,nqpath,&
     160            4 :                      qpath_vertices,nqptfull,qptfull,base_name,gprimd,gmet,prtnest,qptrlatt,&
     161              :                      nsym,symrec) ! optional
     162              : 
     163              : !Arguments ------------------------------------
     164              : !scalars
     165              :  integer,intent(in) :: nband,nkpt,nqpath,prtnest
     166              :  integer, intent(in) :: nqptfull
     167              :  integer, intent(in), optional :: nsym
     168              :  character(len=*),intent(in) :: base_name
     169              : !arrays
     170              :  integer,intent(in) :: kptrlatt(3,3)
     171              :  integer,intent(in),optional :: symrec(3,3,*)
     172              :  real(dp),intent(in) :: gprimd(3,3),kpt(3,nkpt)
     173              :  real(dp),intent(in) :: qptfull(3,nqptfull)
     174              :  real(dp),intent(in) :: gmet(3,3)
     175              :  real(dp),intent(in) :: qpath_vertices(3,nqpath)
     176              :  real(dp),intent(in) :: weight(nband,nkpt)
     177              :  integer,intent(in)  :: qptrlatt(3,3)
     178              : 
     179              : !Local variables-------------------------------
     180              : !scalars
     181              :  integer :: ikpt,jkpt
     182              :  integer :: ik1, ik2, ik3, nkptfull
     183              :  character(len=500) :: msg
     184            4 :  type(krank_t) :: krank
     185              : !arrays
     186            4 :  integer,allocatable :: tmprank(:),ktable(:)
     187              :  character(len=fnlen) :: tmpname
     188            4 :  real(dp),allocatable :: nestfactor(:), nestordered(:), kptfull(:,:)
     189              : ! *************************************************************************
     190              : 
     191              :  if (kptrlatt(1,2) /= 0 .or. kptrlatt(1,3) /= 0 .or. kptrlatt(2,1) /= 0 .or. &
     192            4 :     kptrlatt(2,3) /= 0 .or. kptrlatt(3,1) /= 0 .or. kptrlatt(3,2) /= 0 ) then
     193              :    write (msg,'(4a)')&
     194            0 :     'kptrlatt should be diagonal in order to calculate the nesting factor,',ch10,&
     195            0 :     'skipping the nesting factor calculation ',ch10
     196            0 :    ABI_WARNING(msg)
     197            0 :    return
     198              :  end if
     199              : 
     200            4 :  if (prtnest /= 1 .and. prtnest /= 2) then
     201            0 :    ABI_BUG('prtnest should be 1 or 2')
     202              :  end if
     203              : 
     204              :  !write(msg,'(a,9(i0,1x))')' mknesting : kptrlatt = ',kptrlatt
     205              :  !call wrtout(std_out,msg,'COLL')
     206              : 
     207            4 :  nkptfull = kptrlatt(1,1)*kptrlatt(2,2)*kptrlatt(3,3)
     208          972 :  ABI_CALLOC(nestordered, (nkptfull))
     209           12 :  ABI_MALLOC(kptfull,(3,nkptfull))
     210              : 
     211           28 :  ikpt = 0
     212           28 :  do ik3 = 0, kptrlatt(3,3)-1
     213          172 :    do ik2 = 0, kptrlatt(2,2)-1
     214         1128 :      do ik1 = 0, kptrlatt(1,1)-1
     215          960 :        ikpt = ikpt+1
     216         3984 :        kptfull(:,ikpt) = [dble(ik1)/dble(kptrlatt(1,1)), dble(ik2)/dble(kptrlatt(2,2)),dble(ik3)/dble(kptrlatt(3,3))]
     217              :      end do
     218              :    end do
     219              :  end do
     220              : 
     221              :  ! NOTE: input weights are not normalised, the normalisation factor in introduced in bfactor
     222              :  ! new version now puts kptfull in correct order before bfactor, so no need to re-order...
     223            4 :  if (present(symrec)) then
     224            1 :    ABI_CHECK(present(nsym), "error - provide nsym and symrec arguments together")
     225            1 :    call krank%init(nkpt, kpt, nsym=nsym, symrec=symrec)
     226              :  else
     227            3 :    call krank%init(nkpt, kpt)
     228              :  end if
     229              : 
     230            4 :  call bfactor(nkptfull, kptfull, nkptfull, kptfull, krank, nkpt, weight, nband, nestordered)
     231              : 
     232              :  !================================================================================================
     233              :  !use linear interpolation to plot the bfactor along the given q-path
     234              :  ! 1) order the kpoints of the grid putting them in increasing x, then y, then z (FORTRAN convention)
     235              :  ! 2) make table from input kpts to ordered kpts
     236              :  ! 3) perform interpolation
     237              :  !================================================================================================
     238              : 
     239            4 :  call outnesting(base_name,gmet,gprimd,kptrlatt,nestordered,nkptfull,nqpath,prtnest,qpath_vertices)
     240            4 :  ABI_FREE(nestordered)
     241              : 
     242              :  ! Now do the same, but for the nesting factor over the phonon qpoints only
     243           12 :  ABI_MALLOC(nestfactor, (nqptfull))
     244            4 :  call bfactor(nkptfull,kptfull,nqptfull,qptfull,krank,nkpt,weight,nband,nestfactor)
     245              : 
     246            4 :  call krank%free()
     247            4 :  ABI_FREE(kptfull)
     248              : 
     249            4 :  call krank%init(nqptfull, qptfull)
     250              : 
     251           12 :  ABI_MALLOC(ktable,(nqptfull))
     252           29 :  do ikpt=1,nqptfull
     253           29 :    ktable(ikpt) = ikpt
     254              :  end do
     255              : 
     256            8 :  ABI_MALLOC(tmprank, (nqptfull))
     257           29 :  do ikpt=1,nqptfull
     258           29 :    tmprank(ikpt) = krank%get_rank(qptfull(:,ikpt))
     259              :  end do
     260            4 :  call sort_int(nqptfull, tmprank, ktable)
     261            4 :  ABI_FREE(tmprank)
     262            4 :  call krank%free()
     263              : 
     264              : !fill the datagrid for the nesting factor using the Fortran convention and the conventional unit cell
     265              : !NOTE: the Fortran convention is a must if we want to plot the data
     266              : !in the BXSF format, useful for the linear interpolation since we use interpol3d_0d.F90
     267            8 :  ABI_MALLOC(nestordered,(nqptfull))
     268           29 :  nestordered(:)=zero
     269           29 :  do jkpt=1,nqptfull
     270           25 :    ikpt = ktable(jkpt)
     271           29 :    nestordered(ikpt)=nestfactor(jkpt)
     272              :  end do
     273            4 :  ABI_FREE(nestfactor)
     274            4 :  ABI_FREE(ktable)
     275              : 
     276            4 :  tmpname = trim(base_name)//"kplusq"
     277            4 :  call outnesting(tmpname,gmet,gprimd,qptrlatt,nestordered,nqptfull,nqpath,prtnest,qpath_vertices)
     278              : 
     279            4 :  ABI_FREE(nestordered)
     280              : 
     281            4 : end subroutine mknesting
     282              : !!***
     283              : 
     284              : !----------------------------------------------------------------------
     285              : 
     286              : !!****f* m_nesting/outnesting
     287              : !! NAME
     288              : !! outnesting
     289              : !!
     290              : !! FUNCTION
     291              : !!  Write ou the nesting factors calculated in mknesting
     292              : !!  Data on file in the X-Y format (prtnest 1) or
     293              : !!  in the XCrysden format (XSF)   (prtnest 2)
     294              : !!
     295              : !! INPUTS
     296              : !!  base_name = prefix of the output file
     297              : !!  gmet = metric in reciprocal space
     298              : !!  gprimd(3,3) dimensional reciprocal lattice vectors
     299              : !!  kptrlatt(3,3) basis vectors for k-grid
     300              : !!  nestordered = nesting function on full grid, points ordered in x, then y, then z
     301              : !!  nkpt = number of k points
     302              : !!  nqpath = number of points requested along the trajectory
     303              : !!  prtnest = flags governing the format of the output file
     304              : !!  qpath_vertices = vertices of the reciprocal space trajectory
     305              : !!
     306              : !! OUTPUT
     307              : !!  only write to file
     308              : !!
     309              : !! SOURCE
     310              : 
     311            8 : subroutine outnesting(base_name,gmet,gprimd,kptrlatt,nestordered,nkpt,nqpath,prtnest,qpath_vertices)
     312              : 
     313              : !Arguments ------------------------------------
     314              :  integer,intent(in) :: nqpath,prtnest,nkpt
     315              :  character(len=*),intent(in) :: base_name
     316              : !arrays
     317              :  integer,intent(in) :: kptrlatt(3,3)
     318              :  real(dp),intent(in) :: gprimd(3,3), gmet(3,3)
     319              :  real(dp),intent(in) :: qpath_vertices(3,nqpath), nestordered(nkpt)
     320              : 
     321              : !Local variables-------------------------------
     322              : !scalars
     323              :  integer :: unit_nest,nkx,nky,nkz,indx,ii,ipoint,npt_tot,realrecip
     324              :  character(len=fnlen) :: fname
     325              :  character(len=500) :: msg
     326              :  real(dp) :: res(3), kval
     327              : !arrays
     328           16 :  integer :: ndiv(nqpath-1)
     329            8 :  real(dp),allocatable :: finepath(:,:)
     330              :  real(dp) :: tmpkpt(3),origin(3),qpt(3)
     331              : ! dummy variables for call to printxsf
     332              :  integer :: natom, ntypat, typat(1)
     333              :  real(dp) :: xcart (3,1), znucl(1)
     334              : ! *************************************************************************
     335              : 
     336              :  ! Definition of the q path along which ph linwid will be interpolated
     337            8 :  call make_path(nqpath,qpath_vertices,gmet,'G',20,ndiv,npt_tot,finepath)
     338              : 
     339            8 :  nkx = kptrlatt(1,1)
     340            8 :  nky = kptrlatt(2,2)
     341            8 :  nkz = kptrlatt(3,3)
     342              : 
     343            8 :  if (nkpt /= nkx*nky*nkz) then
     344            0 :    write(msg,'(a,9(i0,1x),2x,i0)')' Wrong input value for kptrlatt  ',kptrlatt, nkpt
     345            0 :    ABI_BUG(msg)
     346              :  end if
     347              : 
     348              :  ! Open output file and write header
     349            8 :  if (open_file(base_name,msg,newunit=unit_nest,status="unknown",form="formatted",action="write") /= 0) then
     350            0 :     ABI_ERROR(msg)
     351              :  end if
     352              : 
     353            8 :  write(unit_nest,'(a)')'#'
     354            8 :  write(unit_nest,'(a)')'# ABINIT package : Nesting factor file'
     355            8 :  write(unit_nest,'(a)')'#'
     356            8 :  write(unit_nest,'(a,i10,a)')'# Nesting factor calculated on ',npt_tot,' Q-points'
     357            8 :  write(unit_nest,'(a)')'# Description of the Q-path :'
     358            8 :  write(unit_nest,'(a,i10)')'# Number of line segments = ',nqpath-1
     359            8 :  write(unit_nest,'(a)')'# Vertices of the Q-path and corresponding index = '
     360            8 :  indx=1
     361           66 :  do ii=1,nqpath
     362           58 :    write(unit_nest,'(a,3(E16.6,1x),i8)')'#  ',qpath_vertices(:,ii),indx
     363           66 :    if(ii<nqpath) indx=indx+ndiv(ii)
     364              :  end do
     365            8 :  write(unit_nest,'(a)')'#'
     366              : 
     367              :  !Get qpoint along the q-path from finepath and interpolate the nesting factor
     368            8 :  indx=1
     369              : 
     370            8 :  write (unit_nest,'(a)')'# index nesting, qfrac_coords'
     371         1592 :  do ipoint=1, npt_tot
     372         6336 :    qpt(:) = finepath(:,ipoint)
     373         6336 :    call wrap2_zero_one(qpt, tmpkpt, res)
     374         1584 :    kval = interpol3d_0d(tmpkpt, nkx, nky, nkz, nestordered)
     375         1584 :    write(unit_nest,'(i5,e16.5,1x,3(es11.4,1x))')indx,kval,tmpkpt
     376         1592 :    indx = indx + 1
     377              :  end do
     378              : 
     379            8 :  close (unit_nest)
     380            8 :  ABI_FREE(finepath)
     381              : 
     382            8 :  if (prtnest==2) then
     383              :    ! write also the nesting factor in the XSF format
     384            0 :    fname = trim(base_name) // '_NEST_XSF'
     385              : 
     386            0 :    if (open_file(fname,msg,newunit=unit_nest,status="unknown",form="formatted",action="write") /= 0) then
     387            0 :       ABI_ERROR(msg)
     388              :    end if
     389              : 
     390            0 :    origin(:) = zero
     391            0 :    realrecip = 1 !reciprocal space
     392            0 :    natom = 1
     393            0 :    ntypat = 1
     394            0 :    typat = [1]
     395            0 :    xcart = reshape ([zero, zero, zero], [3, 1])
     396            0 :    znucl = [one]
     397            0 :    call printxsf(nkx,nky,nkz,nestordered,gprimd,origin,natom, ntypat, typat, xcart, znucl, unit_nest,realrecip)
     398              : 
     399            0 :    close (unit_nest)
     400              :  end if
     401              : 
     402            8 : end subroutine outnesting
     403              : !!***
     404              : 
     405              : end module m_nesting
     406              : !!***
        

Generated by: LCOV version 2.3-1