503 lines
17 KiB
Fortran
503 lines
17 KiB
Fortran
! -*- mode: F90; mode: font-lock -*-
|
|
! ------------------------------------------------------------------------------
|
|
! $Id$
|
|
! ------------------------------------------------------------------------------
|
|
! Module dimens
|
|
! ------------------------------------------------------------------------------
|
|
! Code area 9: general
|
|
! ------------------------------------------------------------------------------
|
|
|
|
!!****h* Conquest/dimens *
|
|
!! NAME
|
|
!! dimens
|
|
!! PURPOSE
|
|
!! Stores various useful dimensions and a subroutine
|
|
!! USES
|
|
!! GenComms, datatypes, global_module, matrix_data, numbers, species_module
|
|
!! AUTHOR
|
|
!! D.R.Bowler
|
|
!! CREATION DATE
|
|
!! 08/05/01 DRB
|
|
!! MODIFICATION HISTORY
|
|
!! 10/05/01 drb
|
|
!! Added blip_width, four_on_blip_width, fobw2, fobw3
|
|
!! 11/06/2001 dave
|
|
!! Added RCS Id and Log tags and altered argument list
|
|
!! to set_dimensions
|
|
!! 20/06/2001 dave
|
|
!! Used cq_abort instead of stop
|
|
!! 18/03/2002 dave
|
|
!! Added header and static object for object file id
|
|
!! 17:28, 2003/06/10 tm
|
|
!! Flag to allow maximum numbers not to be checked
|
|
!! 2006/10/19 16:49 dave
|
|
!! Added automatic grid density finding, and GridCutoff variable
|
|
!! 2008/02/04 17:14 dave
|
|
!! Changes for output to file not stdout
|
|
!! 12:15, 14/02/2008 drb
|
|
!! Added variables for buffer around primary and covering sets
|
|
!! 2011/09/16 11:04 dave
|
|
!! Changed variable atomicrad to atomicnum
|
|
!! 2013/07/01 M.Arita
|
|
!! Commented out some tricks used in MD & structure optimisation
|
|
!! 2016/09/16 16:00 nakata
|
|
!! Added variables for PAO-based matrices and multi-site SFs
|
|
!! SOURCE
|
|
module dimens
|
|
|
|
use datatypes
|
|
use global_module, only: io_lun
|
|
use timer_module, only: start_timer, stop_timer, cq_timer
|
|
use timer_module, only: start_backtrace, stop_backtrace
|
|
|
|
implicit none
|
|
save
|
|
|
|
real(double) :: r_super_x, r_super_y, r_super_z, volume
|
|
real(double) :: r_super_x_squared, r_super_y_squared, r_super_z_squared
|
|
real(double) :: r_s, r_h, r_c, r_nl, r_core_squared, r_dft_d2, r_exx
|
|
real(double) :: r_s_atomf, r_h_atomf, r_MS, r_LD
|
|
real(double) :: grid_point_volume, one_over_grid_point_volume
|
|
real(double) :: support_grid_volume
|
|
real(double) :: GridCutoff, min_blip_sp
|
|
real(double) :: AtomMove_buffer ! Buffer around primary sets and covering sets
|
|
logical :: flag_buffer_old
|
|
!real(double) :: support_grid_spacing, support_grid_volume
|
|
!real(double) :: blip_width, four_on_blip_width, fobw2, fobw3
|
|
|
|
real(double), allocatable, dimension(:) :: RadiusSupport, RadiusAtomf, &
|
|
RadiusMS, RadiusLD, &
|
|
NonLocalFactor, InvSRange
|
|
integer, allocatable, dimension(:) :: atomicnum
|
|
|
|
integer :: n_grid_x, n_grid_y, n_grid_z, n_my_grid_points
|
|
|
|
real(double) :: x_grid, y_grid, z_grid
|
|
|
|
integer, parameter :: ngrids = 105
|
|
!All grid spacings: multiples of 3, 4, 5
|
|
integer, dimension(ngrids), parameter :: grid_spacings = (/ &
|
|
4, 8, 12, 16, 20, 24, 32, 36, 40, 48, &
|
|
60, 64, 72, 80, 96, 100, 108, 120, 128, 144, &
|
|
160, 180, 192, 200, 216, 240, 256, 288, 300, 320, &
|
|
324, 360, 384, 400, 432, 480, 500, 512, 540, 576, &
|
|
600, 640, 648, 720, 768, 800, 864, 900, 960, 972, &
|
|
1000, 1024, 1080, 1152, 1200, 1280, 1296, 1440, 1500, &
|
|
1536, 1600, 1620, 1728, 1800, 1920, 1944, 2000, 2048, 2160,&
|
|
2304, 2400, 2500, 2560, 2592, 2700, 2880, 3000, 3072, 3200,&
|
|
3240, 3456, 3600, 3840, 3888, 4000, 4096, 4320, 4500, &
|
|
4608, 4800, 5000, 5120, 5184, 5400, 5760, 6000, 6144, 6400,&
|
|
6480, 6912, 7200, 7500, 7680, 8000, 8192 /)
|
|
|
|
!!***
|
|
|
|
contains
|
|
|
|
! -----------------------------------------------------------
|
|
! Subroutine set_dimensions
|
|
! -----------------------------------------------------------
|
|
|
|
!!****f* dimens/set_dimensions *
|
|
!!
|
|
!! NAME
|
|
!! set_dimensions
|
|
!! USAGE
|
|
!!
|
|
!! PURPOSE
|
|
!! Sets up various parameters and dimensions
|
|
!! INPUTS
|
|
!!
|
|
!!
|
|
!! USES
|
|
!!
|
|
!! AUTHOR
|
|
!! EHH, CMG, D.R.Bowler
|
|
!! CREATION DATE
|
|
!! 5/5/95
|
|
!! MODIFICATION HISTORY
|
|
!! 3/10/95 CMG
|
|
!! 23/1/96 EHH/CMG Added dimension setting
|
|
!! 08/05/01 DRB changed format to ROBODoc and simplified output
|
|
!! 10/05/01 DRB added matrix names
|
|
!! 11/06/2001 dave
|
|
!! Changed to pass data from pseudopotential_data
|
|
!! 20/06/2001 dave
|
|
!! Used cq_abort instead of stop
|
|
!! 15:57, 04/02/2003 drb
|
|
!! Changed scan over core radii to be for ALL cases: we need this
|
|
!! for local pseudos too
|
|
!! 12:17, 2004/06/09 dave
|
|
!! Added scan for separate InvSrange to allow larger radii.
|
|
!! 2007/04/17 09:42 dave
|
|
!! Removed rcut_dens
|
|
!! 2008/03/03 18:44 dave
|
|
!! Changed float to real
|
|
!! 2008/03/12 06:13 dave
|
|
!! Added loop to find longest range matrix
|
|
!! 2009/07/08 16:40 dave
|
|
!! Zero r_t
|
|
!! 2011/09/29 M. Arita
|
|
!! Set the cutoff for DFT-D2
|
|
!! 2013/07/03 M.Arita
|
|
!! Introduced flag_MDold to choose the way of member updates.
|
|
!! Now the code does not expand cutoff ranges automatically by default.
|
|
!! 2014/01/17 lat
|
|
!! Added r_nl: fix unconsistency between HNL_fac/NonLocalFactor
|
|
!! 2014/01/17 lat
|
|
!! Added r_exx and assigned to rcut(Xrange)
|
|
!! 2016/09/16 16:00 nakata
|
|
!! Set ranges of atomf-based matrices
|
|
!! 2016/11/02 dave
|
|
!! Added flag so that we only warn Lrange<Srange if O(N) is used
|
|
!! 2017/03/08 15:00 nakata
|
|
!! Removed dSrange, dHrange and PAOPrange which are no longer used
|
|
!! 2017/02/23 dave
|
|
!! - Changing location of diagon flag from DiagModule to global and name to flag_diagonalisation
|
|
!! 2017/12/05 11:00 dave
|
|
!! Adding NA projector ranges
|
|
!! 2018/05/15 12:21 dave
|
|
!! Bug fix: mataNA range was wrong with MSSF (didn't correctly use atom function ranges)
|
|
!! 2019/11/18 tsuyoshi
|
|
!! flag_MDold was removed.
|
|
!! 2019/12/02 15:17 dave
|
|
!! Added checks to round RadiusAtomf and RadiusSupport to safe value (including grid points)
|
|
!! SOURCE
|
|
!!
|
|
subroutine set_dimensions(inode, ionode,HNL_fac,non_local, n_species, non_local_species, core_radius)
|
|
|
|
use datatypes
|
|
use numbers
|
|
use matrix_data
|
|
use GenComms, only: cq_abort, cq_warn
|
|
use global_module, only: iprint_init, atomf, sf, flag_Multisite, flag_exx, flag_diagonalisation
|
|
use block_module, only: in_block_x, in_block_y, in_block_z, n_pts_in_block
|
|
use pseudopotential_common, only: pseudo_type, OLDPS, SIESTA, ABINIT, flag_neutral_atom_projector
|
|
|
|
implicit none
|
|
|
|
! Passed variables
|
|
logical :: non_local, non_local_species(:)
|
|
integer :: inode, ionode, n_species
|
|
|
|
real(double) :: HNL_fac, core_radius(:)
|
|
|
|
! Local variables
|
|
character(len=80) :: sub_name = "set_dimensions"
|
|
type(cq_timer) :: backtrace_timer
|
|
integer :: n, mx_matrices_tmp
|
|
real(double) :: r_core, r_t, rcutmax, max_grid
|
|
|
|
!****lat<$
|
|
call start_backtrace(t=backtrace_timer,who='set_dimensions',where=9,level=2)
|
|
!****lat>$
|
|
|
|
! Various grid parameters
|
|
r_super_x_squared = r_super_x * r_super_x
|
|
r_super_y_squared = r_super_y * r_super_y
|
|
r_super_z_squared = r_super_z * r_super_z
|
|
volume = r_super_x * r_super_y * r_super_z
|
|
grid_point_volume = volume/(n_grid_x*n_grid_y*n_grid_z)
|
|
one_over_grid_point_volume = one / grid_point_volume
|
|
!support_grid_volume = support_grid_spacing**3
|
|
x_grid = one / real( n_grid_x, double)
|
|
y_grid = one / real( n_grid_y, double)
|
|
z_grid = one / real( n_grid_z, double)
|
|
! Calculate largest grid spacing in any direction (local to routine for now)
|
|
max_grid = max(r_super_x*x_grid,r_super_y*y_grid,r_super_z*z_grid)
|
|
! Grid points in a block
|
|
n_pts_in_block = in_block_x * in_block_y * in_block_z
|
|
|
|
! Set indices for atomf-based-matrix ranges
|
|
if (atomf==sf) then
|
|
aSa_range = Srange
|
|
aHa_range = Hrange
|
|
if(flag_neutral_atom_projector) then
|
|
aNArange = 20
|
|
NAarange = 21
|
|
mx_matrices_tmp = 21
|
|
else
|
|
mx_matrices_tmp = 19
|
|
end if
|
|
else
|
|
aSa_range = 20
|
|
aHa_range = 21
|
|
STr_range = 22
|
|
HTr_range = 23
|
|
aSs_range = 24
|
|
aHs_range = 25
|
|
sSa_range = 26
|
|
sHa_range = 27
|
|
SFcoeff_range = 28
|
|
SFcoeffTr_range = 29
|
|
LD_range = 30
|
|
if(flag_neutral_atom_projector) then
|
|
aNArange = 31
|
|
NAarange = 32
|
|
mx_matrices_tmp = mx_matrices ! = 30
|
|
else
|
|
mx_matrices_tmp = 30
|
|
end if
|
|
endif
|
|
|
|
!n_my_grid_points = n_pts_in_block * n_blocks
|
|
! decide if the flag non_local needs to be set to true
|
|
if(pseudo_type == OLDPS) then
|
|
non_local = .false.
|
|
do n=1, n_species
|
|
if(non_local_species(n)) non_local = .true.
|
|
end do
|
|
elseif(pseudo_type == SIESTA.OR.pseudo_type==ABINIT) then
|
|
non_local = .true.
|
|
else
|
|
call cq_abort('ERROR : pseudo_type in set_dimension',pseudo_type)
|
|
endif
|
|
|
|
! we need to decide which is the largest core radius
|
|
r_core = zero
|
|
r_h = zero
|
|
r_t = zero
|
|
r_nl = zero
|
|
r_h_atomf = zero
|
|
r_MS = zero
|
|
r_LD = zero
|
|
do n=1, n_species
|
|
! Round the atom function radius to the nearest multiple of the largest grid spacing
|
|
! (add one to account for displacement relative to grid point)
|
|
RadiusAtomf(n) = max_grid*(floor(RadiusAtomf(n)/max_grid)+two)
|
|
RadiusSupport(n) = max(RadiusSupport(n), RadiusAtomf(n))
|
|
r_core = max(r_core,core_radius(n))
|
|
r_h = max(r_h,RadiusSupport(n))
|
|
r_t = max(r_t,InvSRange(n))
|
|
r_nl = max(r_nl,NonLocalFactor(n)*core_radius(n))
|
|
r_h_atomf = max(r_h_atomf,RadiusAtomf(n))
|
|
r_MS = max(r_MS,RadiusMS(n))
|
|
r_LD = max(r_LD,RadiusLD(n))
|
|
end do
|
|
if(non_local.and.(inode==ionode).and.iprint_init>0) then
|
|
write(io_lun,2) r_core
|
|
2 format(8x,'This calculation includes non-local pseudopotentials,'/&
|
|
9x,'with a maximum core radius of ',f15.8)
|
|
end if
|
|
if (r_core-r_h>1e-4_double) then
|
|
call cq_abort('set_dimens: r_core > r_support',r_core,r_h)
|
|
end if
|
|
|
|
! then, obtain the blip width
|
|
!four_on_blip_width = four / blip_width
|
|
!fobw2 = four_on_blip_width*four_on_blip_width
|
|
!fobw3 = four_on_blip_width*fobw2
|
|
|
|
! Set range of S matrix
|
|
r_s = r_h
|
|
r_s_atomf = r_h_atomf
|
|
if(two*r_s>r_c.AND.(.NOT.flag_diagonalisation)) then ! Only warn if using O(N)
|
|
call cq_warn(sub_name, "S range greater than L !",two*r_s,r_c)
|
|
endif
|
|
! Set ranges for contracted SFs
|
|
if (flag_Multisite) then
|
|
r_s = r_s_atomf + r_MS
|
|
r_h = r_h_atomf + r_MS
|
|
if (r_t.lt.r_s) r_t = r_s
|
|
endif
|
|
|
|
! Set other ranges
|
|
r_core_squared = r_core * r_core
|
|
! Set matrix ranges (from matrix_data)
|
|
if (HNL_fac <= 0.1_double) then
|
|
rcut(Hrange) = (two*(r_h + r_nl))
|
|
else
|
|
rcut(Hrange) = (two*(r_h+HNL_fac*r_core))
|
|
end if
|
|
|
|
! **< lat >** don't touch
|
|
if(flag_exx) then
|
|
if( rcut(Xrange) > rcut(Hrange) ) then
|
|
rcut(Hrange) = rcut(Xrange)
|
|
rcut(SXrange) = rcut(Hrange)
|
|
!
|
|
else if ( rcut(Xrange) <= zero ) then
|
|
rcut(Xrange) = rcut(Hrange)
|
|
rcut(SXrange) = rcut(Hrange)
|
|
!
|
|
else
|
|
rcut(Xrange) = two*r_exx
|
|
rcut(SXrange) = two*r_exx
|
|
!
|
|
endif
|
|
else
|
|
rcut(Xrange) = two
|
|
rcut(SXrange) = two
|
|
end if
|
|
|
|
! New 16:25, 2014/08/29 **< lat >**
|
|
!rcut(Hrange) = (two*(r_h + r_nl))
|
|
!rcut(Hrange) = (two*(r_h+HNL_fac*r_core))
|
|
rcut(Srange) = (two*r_s)
|
|
rcut(Trange) = (two*r_t)
|
|
rcut(Lrange) = (r_c)
|
|
rcut(APrange) = (r_core + r_h_atomf)
|
|
rcut(LSrange) = (rcut(Lrange) + rcut(Srange))
|
|
rcut(LHrange) = (rcut(Lrange) + rcut(Hrange))
|
|
rcut(LSLrange) = (two*rcut(Lrange) + rcut(Srange))
|
|
rcut(SLSrange) = (two*rcut(Srange) + rcut(Lrange))
|
|
! New 12:16, 2004/06/09 dave
|
|
!rcut(Trange) = (rcut(Srange))
|
|
rcut(TSrange) = (rcut(Trange)+rcut(Srange))
|
|
rcut(THrange) = (rcut(Trange)+rcut(Hrange))
|
|
rcut(TLrange) = (rcut(Trange)+rcut(Lrange))
|
|
rcut(PArange) = rcut(APrange)
|
|
rcut(LTrrange) = rcut(Lrange)
|
|
rcut(SLrange) = rcut(LSrange)
|
|
rcut(TTrrange) = rcut(Trange)
|
|
rcut(HLrange) = rcut(LHrange)
|
|
! for atomf-based matrices
|
|
if (atomf.ne.sf) then
|
|
rcut(aSa_range) = two*r_s_atomf
|
|
rcut(aHa_range) = rcut(Hrange) - two*r_MS ! = two*(r_h_atomf+HNL_fac*r_core)
|
|
rcut(STr_range) = rcut(Srange)
|
|
rcut(HTr_range) = rcut(Hrange)
|
|
rcut(aSs_range) = r_s_atomf + r_s
|
|
rcut(aHs_range) = rcut(Hrange) - r_MS ! = (r_h_atomf+HNL_fac*r_core)+(r_h+HNL_fac*r_core)
|
|
rcut(sSa_range) = rcut(aSs_range)
|
|
rcut(sHa_range) = rcut(aHs_range)
|
|
rcut(SFcoeff_range) = r_MS
|
|
rcut(SFcoeffTr_range) = r_MS
|
|
rcut(LD_range) = r_LD
|
|
if (abs(r_MS)<very_small) then
|
|
rcut(SFcoeff_range) = 0.001_double
|
|
rcut(SFcoeffTr_range) = 0.001_double
|
|
endif
|
|
if (abs(r_LD)<very_small) rcut(LD_range) = 0.001_double
|
|
endif
|
|
if(flag_neutral_atom_projector) then
|
|
rcut(aNArange) = r_s_atomf + r_h_atomf
|
|
rcut(NAarange) = rcut(aNArange)
|
|
mat_name(aNArange) = "aNA"
|
|
mat_name(NAarange) = "NAa"
|
|
end if
|
|
rcutmax = zero
|
|
do n=1,mx_matrices_tmp
|
|
if(rcut(n)>rcutmax) then
|
|
max_range = n
|
|
rcutmax = rcut(n)
|
|
end if
|
|
enddo
|
|
! Seemingly trivial, but may be quite useful - matrix names
|
|
! agreed... 2014/08/29 LAT
|
|
mat_name(Srange) = "S "
|
|
mat_name(Lrange) = "L "
|
|
mat_name(Hrange) = "H "
|
|
mat_name(APrange) = "AP "
|
|
mat_name(LSrange) = "LS "
|
|
mat_name(LHrange) = "LH "
|
|
mat_name(LSLrange) = "LSL"
|
|
mat_name(SLSrange) = "SLS"
|
|
mat_name(Trange) = "T "
|
|
mat_name(TSrange) = "TS "
|
|
mat_name(THrange) = "TH "
|
|
mat_name(TLrange) = "TL "
|
|
mat_name(PArange) = "PA "
|
|
mat_name(LTrrange) = "LT "
|
|
mat_name(SLrange) = "SL "
|
|
mat_name(TTrrange) = "TT "
|
|
mat_name(HLrange) = "HL "
|
|
mat_name(Xrange) = "X "
|
|
mat_name(SXrange) = "SX "
|
|
if (atomf.ne.sf) then
|
|
mat_name(aSa_range) = "aSa"
|
|
mat_name(aHa_range) = "aHa"
|
|
mat_name(STr_range) = "St"
|
|
mat_name(HTr_range) = "Ht"
|
|
mat_name(aSs_range) = "aSs"
|
|
mat_name(aHs_range) = "aHs"
|
|
mat_name(sSa_range) = "sSa"
|
|
mat_name(sHa_range) = "sHa"
|
|
mat_name(SFcoeff_range) = "MS"
|
|
mat_name(SFcoeffTr_range) = "MSt"
|
|
mat_name(LD_range) = "LD"
|
|
endif
|
|
if(inode==ionode.AND.iprint_init>1) then
|
|
do n=1,mx_matrices_tmp
|
|
write(io_lun,1) mat_name(n),rcut(n)
|
|
enddo
|
|
endif
|
|
1 format(8x,'Matrix ',a3,' has range ',f15.8)
|
|
!****lat<$
|
|
call stop_backtrace(t=backtrace_timer,who='set_dimensions')
|
|
!****lat>$
|
|
|
|
return
|
|
end subroutine set_dimensions
|
|
!!***
|
|
|
|
subroutine find_grid
|
|
|
|
use datatypes
|
|
use numbers, only: pi, very_small,two, half
|
|
use global_module, only: iprint_init, flag_basis_set, blips
|
|
use GenComms, only: inode,ionode,cq_abort, cq_warn
|
|
|
|
implicit none
|
|
|
|
! Local variables
|
|
character(len=80) :: sub_name="find_grid"
|
|
type(cq_timer) :: backtrace_timer
|
|
real(double) :: sqKE, blipKE, blip_sp
|
|
integer :: mingrid, i
|
|
|
|
!****lat<$
|
|
call start_backtrace(t=backtrace_timer,who='find_grid',where=9,level=2)
|
|
!****lat>$
|
|
|
|
if(n_grid_x>0.AND.n_grid_y>0.AND.n_grid_z>0) then ! We dont need to find grids
|
|
if(iprint_init>1.AND.inode==ionode) &
|
|
write(io_lun,fmt='(2x,"User specified grid dimensions: ",3i5)') n_grid_x,n_grid_y,n_grid_z
|
|
call stop_backtrace(t=backtrace_timer,who='find_grid')
|
|
return
|
|
else
|
|
if(GridCutoff<very_small) call cq_abort("Grid cutoff too small: ",GridCutoff)
|
|
if(flag_basis_set==blips) then ! Test for fine enough grid
|
|
blip_sp = half*min_blip_sp
|
|
blipKE = half*(pi/blip_sp)*(pi/blip_sp)
|
|
if(GridCutoff<blipKE) then
|
|
if(iprint_init>0) call cq_warn(sub_name, "Adjusted grid cutoff to ",blipKE)
|
|
GridCutoff = blipKE
|
|
end if
|
|
end if
|
|
sqKE = sqrt(two*GridCutoff) ! Use KE = 0.5*G*G
|
|
! For now, we assume orthorhombic cells
|
|
! x first
|
|
mingrid = int(sqKE*r_super_x/pi)
|
|
do i=1,ngrids
|
|
if(grid_spacings(i)>mingrid) then
|
|
n_grid_x = grid_spacings(i)
|
|
exit
|
|
end if
|
|
end do
|
|
! y
|
|
mingrid = int(sqKE*r_super_y/pi)
|
|
do i=1,ngrids
|
|
if(grid_spacings(i)>mingrid) then
|
|
n_grid_y = grid_spacings(i)
|
|
exit
|
|
end if
|
|
end do
|
|
! z
|
|
mingrid = int(sqKE*r_super_z/pi)
|
|
do i=1,ngrids
|
|
if(grid_spacings(i)>mingrid) then
|
|
n_grid_z = grid_spacings(i)
|
|
exit
|
|
end if
|
|
end do
|
|
endif
|
|
|
|
!****lat<$
|
|
call stop_backtrace(t=backtrace_timer,who='find_grid')
|
|
!****lat>$
|
|
|
|
return
|
|
end subroutine find_grid
|
|
|
|
end module dimens
|