25 use,
intrinsic :: iso_fortran_env
75 real(real64),
allocatable :: point(:, :)
76 real(real64),
allocatable :: point1BZ(:, :)
77 real(real64),
allocatable :: red_point(:, :)
78 real(real64),
allocatable :: weight(:)
79 integer,
allocatable :: equiv(:)
80 integer :: nshifts = 1
81 real(real64),
allocatable :: shifts(:, :)
82 integer :: npoints = 0
89 type(lattice_vectors_t) :: latt
91 type(kpoints_grid_t) :: full
92 type(kpoints_grid_t) :: reduced
93 type(simplex_t),
pointer :: simplex
97 logical :: use_symmetries = .false.
98 logical :: use_time_reversal = .false.
99 integer :: nik_skip = 0
102 integer,
allocatable :: nik_axis(:)
103 integer,
allocatable :: niq_axis(:)
104 integer,
allocatable,
private :: symmetry_ops(:, :)
105 integer,
allocatable,
private :: num_symmetry_ops(:)
108 real(real64),
allocatable,
private :: coord_along_path(:)
110 integer,
allocatable :: downsampling(:)
112 type(symmetries_t),
pointer :: symm => null()
125 integer,
public,
parameter :: &
135 integer,
intent(in) :: dim
136 type(kpoints_grid_t),
intent(out) :: this
137 integer,
intent(in) :: npoints
138 integer,
intent(in) :: nshifts
143 this%npoints = npoints
144 this%nshifts = nshifts
145 safe_allocate(this%red_point(1:dim, 1:npoints))
146 safe_allocate(this%point(1:dim, 1:npoints))
147 safe_allocate(this%point1bz(1:dim,1:npoints))
148 safe_allocate(this%weight(1:npoints))
149 safe_allocate(this%equiv(1:npoints))
150 safe_allocate(this%shifts(1:dim,1:nshifts))
157 type(kpoints_grid_t),
intent(inout) :: this
161 safe_deallocate_a(this%red_point)
162 safe_deallocate_a(this%point)
163 safe_deallocate_a(this%point1BZ)
164 safe_deallocate_a(this%weight)
165 safe_deallocate_a(this%equiv)
166 safe_deallocate_a(this%shifts)
180 aa%weight(1:bb%npoints) = bb%weight(1:bb%npoints)
181 aa%equiv(1:bb%npoints) = bb%equiv(1:bb%npoints)
182 aa%point(1:bb%dim, 1:bb%npoints) = bb%point(1:bb%dim, 1:bb%npoints)
183 aa%point1BZ(1:bb%dim, 1:bb%npoints) = bb%point1BZ(1:bb%dim, 1:bb%npoints)
184 aa%red_point(1:bb%dim, 1:bb%npoints) = bb%red_point(1:bb%dim, 1:bb%npoints)
185 aa%shifts(1:bb%dim, 1:bb%nshifts) = bb%shifts(1:bb%dim, 1:bb%nshifts)
199 if (.not.
allocated(that%point))
then
204 if (.not.
allocated(this%point))
then
222 this%red_point(1:old_grid%dim, 1:old_grid%npoints)= old_grid%red_point(1:old_grid%dim, 1:old_grid%npoints)
223 this%point(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point(1:old_grid%dim, 1:old_grid%npoints)
224 this%point1BZ(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point1BZ(1:old_grid%dim, 1:old_grid%npoints)
225 this%weight(1:old_grid%npoints) = old_grid%weight(1:old_grid%npoints)
226 this%equiv(1:old_grid%npoints) = old_grid%equiv(1:old_grid%npoints)
227 this%shifts(1:old_grid%dim, 1:old_grid%nshifts) = old_grid%shifts(1:old_grid%dim, 1:old_grid%nshifts)
230 this%red_point(1:old_grid%dim, old_grid%npoints+1:this%npoints)= that%red_point(1:that%dim, 1:that%npoints)
231 this%point(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point(1:that%dim, 1:that%npoints)
232 this%point1BZ(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point1BZ(1:that%dim, 1:that%npoints)
233 this%weight(old_grid%npoints+1:this%npoints) = that%weight(1:that%npoints)
234 this%equiv(old_grid%npoints+1:this%npoints) = that%equiv(1:that%npoints)
246 logical,
intent(in) :: use_symmetries
247 logical,
intent(in) :: only_gamma
256 method = kpoints_gamma
269 if (use_symmetries)
then
270 write(
message(1),
'(a)')
"User-defined k-points are not compatible with KPointsUseSymmetries=yes."
278 if (use_symmetries)
then
279 write(
message(1),
'(a)')
"KPointsPath is not compatible with KPointsUseSymmetries=yes."
284 if (method == 0)
then
285 write(
message(1),
'(a)')
"Unable to determine the method for defining k-points."
286 write(
message(2),
'(a)')
"Octopus will continue assuming a Monkhorst Pack grid."
299 integer,
intent(in) :: dim
306 this%simplex => null()
308 safe_allocate(this%nik_axis(1:dim))
309 safe_allocate(this%niq_axis(1:dim))
310 safe_allocate(this%downsampling(1:dim))
314 this%downsampling = 1
321 subroutine kpoints_init(this, namespace, symm, dim, periodic_dim, latt)
325 integer,
intent(in) :: dim
326 integer,
intent(in) :: periodic_dim
329 logical :: only_gamma, default_timereversal
350 call parse_variable(namespace,
'KPointsUseSymmetries', .false., this%use_symmetries)
370 call parse_variable(namespace,
'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
372 only_gamma = (periodic_dim == 0)
404 integer,
intent(in) :: dim
405 logical,
intent(in) :: gamma_only
407 logical :: gamma_only_
408 integer :: ii, ik, is, ncols, nshifts
410 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
411 real(real64),
allocatable :: shifts(:, :)
459 gamma_only_ = gamma_only
460 if (.not. gamma_only_)
then
461 gamma_only_ = (
parse_block(namespace,
'KPointsGrid', blk) /= 0)
466 if (.not. gamma_only_)
then
471 safe_allocate(shifts(1:dim,1:nshifts))
474 if (.not. gamma_only_)
then
476 if (ncols /= dim)
then
477 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid first row has ', ncols,
' columns but should have ', dim
478 if (ncols < dim)
then
481 write(
message(2),
'(a)')
'Continuing, but ignoring the additional values.'
489 if (any(this%nik_axis < 1))
then
490 message(1) =
'Input: KPointsGrid is not valid.'
496 if (ncols /= dim)
then
497 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid shift has ', ncols,
' columns but must have ', dim
508 if (mod(this%nik_axis(ii), 2) /= 0)
then
538 this%niq_axis(:) = this%nik_axis(:)
539 this%downsampling(:) = 1
541 if (
parse_block(namespace,
'QPointsGrid', blk) == 0)
then
543 if (ncols /= dim)
then
544 write(
message(1),
'(a,i3,a,i3)')
'QPointsGrid first row has ', ncols,
' columns but must have ', dim
551 if (any(this%nik_axis/this%niq_axis /= nint(this%nik_axis/real(this%niq_axis))))
then
552 message(1) =
'Input: QPointsGrid is not compatible with the KPointsGrid.'
556 this%downsampling = this%nik_axis/this%niq_axis
558 if (any(this%downsampling /= 1) .and. this%use_symmetries)
then
569 this%full%shifts(:, :) = shifts(:, :)
570 safe_deallocate_a(shifts)
572 call kpoints_grid_generate(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point)
574 do ik = 1, this%full%npoints
578 this%full%weight =
m_one / this%full%npoints
581 do ik = 1, this%full%npoints
582 this%full%equiv(ik) = ik
585 if (this%use_symmetries)
then
586 message(1) =
"Checking if the generated full k-point grid is symmetric"
593 if (this%use_symmetries)
then
594 safe_allocate(num_symm_ops(1:this%full%npoints))
596 if (this%use_time_reversal)
then
603 this%reduced%npoints, dim, this%reduced%red_point, this%reduced%weight, this%reduced%equiv, symm_ops, num_symm_ops)
605 assert(maxval(num_symm_ops) >= 1)
606 if (this%use_time_reversal)
then
613 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
615 do ik = 1, this%reduced%npoints
616 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
619 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)))
620 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
622 this%num_symmetry_ops(1:this%reduced%npoints) = num_symm_ops(1:this%reduced%npoints)
623 this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)) = &
624 symm_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops))
626 safe_deallocate_a(num_symm_ops)
627 safe_deallocate_a(symm_ops)
629 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
630 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1))
631 this%num_symmetry_ops(1:this%reduced%npoints) = 1
632 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
635 do ik = 1, this%reduced%npoints
636 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
643 integer(int64) :: dos_method, smearing_function
644 logical :: use_simplex, use_simplex_opt
646 call parse_variable(namespace,
'DOSMethod', option__dosmethod__smear, dos_method)
647 call parse_variable(namespace,
'SmearingFunction', option__smearingfunction__semiconducting, smearing_function)
649 use_simplex = dos_method == option__dosmethod__tetrahedra .or. &
650 smearing_function == option__smearingfunction__tetrahedra
651 use_simplex_opt = dos_method == option__dosmethod__tetrahedra_opt .or. &
652 smearing_function == option__smearingfunction__tetrahedra_opt
654 if (use_simplex .and. use_simplex_opt)
then
655 call messages_not_implemented(
"DOSMethod and SmearingFunction with different tetrahedron methods", namespace=namespace)
658 if ((use_simplex .or. use_simplex_opt) .and.
associated(this%simplex))
then
659 safe_deallocate_p(this%simplex)
662 if (use_simplex)
then
663 this%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
664 this%reduced%equiv, opt = .false.)
665 elseif (use_simplex_opt)
then
666 this%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
667 this%reduced%equiv, opt = .
true.)
678 type(namespace_t),
intent(in) :: namespace
679 integer,
intent(in) :: dim
682 integer :: nshifts, nkpoints, nhighsympoints, nsegments
683 integer :: icol, ik, idir, ncols, npoints
684 integer,
allocatable :: resolution(:)
685 real(real64),
allocatable :: highsympoints(:, :)
687 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
715 if (parse_block(namespace,
'KPointsPath', blk) /= 0)
then
716 write(message(1),
'(a)')
'Internal error while reading KPointsPath.'
717 call messages_fatal(1, namespace=namespace)
721 nsegments = parse_block_cols(blk, 0)
722 nhighsympoints = parse_block_n(blk) - 1
723 if (nhighsympoints /= nsegments + 1)
then
724 write(message(1),
'(a,i3,a,i3)')
'The first row of KPointsPath is not compatible with the number of specified k-points.'
725 call messages_fatal(1, namespace=namespace)
728 safe_allocate(resolution(1:nsegments))
729 do icol = 1, nsegments
730 call parse_block_integer(blk, 0, icol-1, resolution(icol))
733 nkpoints = sum(resolution) + 1
735 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
736 do ik = 1, nhighsympoints
737 ncols = parse_block_cols(blk, ik)
738 if (ncols /= dim)
then
739 write(message(1),
'(a,i8,a,i3,a,i3)')
'KPointsPath row ', ik,
' has ', ncols,
' columns but must have ', dim
740 call messages_fatal(1, namespace=namespace)
744 call parse_block_float(blk, ik, idir-1, highsympoints(idir, ik))
748 call parse_block_end(blk)
755 safe_allocate(this%coord_along_path(1:nkpoints))
757 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
758 this%coord_along_path)
760 safe_deallocate_a(resolution)
761 safe_deallocate_a(highsympoints)
766 path_kpoints_grid%weight = m_one/path_kpoints_grid%npoints
768 path_kpoints_grid%weight = m_zero
769 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
773 do ik = 1, path_kpoints_grid%npoints
774 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
781 if (
allocated(this%symmetry_ops))
then
782 npoints = this%reduced%npoints
783 safe_allocate(num_symm_ops(1:npoints))
784 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
786 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
787 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
788 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
794 if (
allocated(this%symmetry_ops))
then
795 safe_deallocate_a(this%num_symmetry_ops)
796 safe_deallocate_a(this%symmetry_ops)
797 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
798 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
800 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
801 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
802 symm_ops(1:npoints, 1:maxval(num_symm_ops))
803 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
804 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
806 safe_deallocate_a(num_symm_ops)
807 safe_deallocate_a(symm_ops)
808 else if(this%use_symmetries)
then
809 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
810 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
812 this%num_symmetry_ops(1:this%reduced%npoints) = 1
813 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
825 type(namespace_t),
intent(in) :: namespace
826 integer,
intent(in) :: dim
831 real(real64) :: weight_sum
869 if (parse_block(namespace,
'KPoints', blk) /= 0)
then
870 if (parse_block(namespace,
'KPointsReduced', blk) == 0)
then
874 write(message(1),
'(a)')
'Internal error loading user-defined k-point list.'
875 call messages_fatal(1, namespace=namespace)
881 user_kpoints_grid%red_point = m_zero
882 user_kpoints_grid%point = m_zero
883 user_kpoints_grid%weight = m_zero
884 user_kpoints_grid%equiv = 0
885 user_kpoints_grid%shifts = m_zero
888 do ik = 1, user_kpoints_grid%npoints
889 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
891 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%red_point(idir, ik))
894 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
897 do ik = 1, user_kpoints_grid%npoints
898 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
900 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%point(idir, ik), unit_one/units_inp%length)
903 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
906 call parse_block_end(blk)
909 if (any(user_kpoints_grid%weight < m_epsilon))
then
910 call messages_experimental(
'K-points with zero weight')
911 message(1) =
"Found k-points with zero weight. They are excluded from density calculation"
912 call messages_warning(1, namespace=namespace)
917 do ik=1,user_kpoints_grid%npoints
918 if (user_kpoints_grid%weight(ik) < m_epsilon)
then
920 if (ik < user_kpoints_grid%npoints)
then
921 if (user_kpoints_grid%weight(ik+1) > m_epsilon)
then
922 message(1) =
"K-points with zero weight must follow all regular k-points in a block"
923 call messages_fatal(1, namespace=namespace)
926 this%nik_skip = this%nik_skip + 1
927 user_kpoints_grid%weight(ik) = m_zero
932 weight_sum = sum(user_kpoints_grid%weight)
933 if (weight_sum < m_epsilon)
then
934 message(1) =
"k-point weights must sum to a positive number."
935 call messages_fatal(1, namespace=namespace)
937 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
947 write(message(1),
'(a,i4,a)')
'Input: ', user_kpoints_grid%npoints,
' k-points were read from the input file'
948 call messages_info(1, namespace=namespace)
964 safe_deallocate_a(this%nik_axis)
965 safe_deallocate_a(this%niq_axis)
966 safe_deallocate_a(this%downsampling)
967 safe_deallocate_a(this%symmetry_ops)
968 safe_deallocate_a(this%num_symmetry_ops)
969 safe_deallocate_a(this%coord_along_path)
970 safe_deallocate_p(this%simplex)
978 type(namespace_t),
intent(in) :: namespace
980 integer :: idir, is, ik, dim
981 character(len=100) :: str_tmp
985 dim = this%reduced%dim
988 write(message(1),
'(a)')
' '
989 write(message(2),
'(1x,i5,a)') this%reduced%npoints,
' k-points generated from parameters :'
990 write(message(3),
'(1x,a)')
'---------------------------------------------------'
991 write(message(4),
'(4x,a)')
'n ='
993 write(str_tmp,
'(i5)') this%nik_axis(idir)
994 message(4) = trim(message(4)) // trim(str_tmp)
996 call messages_info(4, namespace=namespace)
998 do is = 1, this%reduced%nshifts
999 write(message(1),
'(a)')
' '
1000 write(message(2),
'(4x,a,i1,a)')
's', is,
' ='
1002 write(str_tmp,
'(f6.2)') this%reduced%shifts(idir,is)
1003 message(2) = trim(message(2)) // trim(str_tmp)
1005 call messages_info(2, namespace=namespace)
1009 write(message(1),
'(a)')
' '
1010 write(message(2),
'(a)')
' index | weight | coordinates |'
1011 call messages_info(2, namespace=namespace)
1013 do ik = 1, this%reduced%npoints
1014 write(str_tmp,
'(i8,a,f12.6,a)') ik,
" | ", this%reduced%weight(ik),
" |"
1015 message(1) = str_tmp
1017 write(str_tmp,
'(f12.6)') this%reduced%red_point(idir, ik)
1018 message(1) = trim(message(1)) // trim(str_tmp)
1020 write(str_tmp,
'(a)')
" |"
1021 message(1) = trim(message(1)) // trim(str_tmp)
1022 call messages_info(1, namespace=namespace)
1025 write(message(1),
'(a)')
' '
1026 call messages_info(1, namespace=namespace)
1034 type(lattice_vectors_t),
intent(in) :: latt
1035 real(real64),
intent(in) :: kin(:)
1036 real(real64),
intent(out) :: kout(:)
1040 kout = matmul(latt%klattice, kin)
1047 type(lattice_vectors_t),
intent(in) :: latt
1048 real(real64),
intent(in) :: kin(:)
1049 real(real64),
intent(out) :: kout(:)
1053 kout = matmul(kin, latt%rlattice) / (m_two*m_pi)
1068 kout%method = kin%method
1073 kout%use_symmetries = kin%use_symmetries
1074 kout%use_time_reversal = kin%use_time_reversal
1076 safe_allocate(kout%nik_axis(1:kin%full%dim))
1077 safe_allocate(kout%niq_axis(1:kin%full%dim))
1078 safe_allocate(kout%downsampling(1:kin%full%dim))
1079 kout%nik_axis(:) = kin%nik_axis(:)
1080 kout%niq_axis(:) = kin%niq_axis(:)
1081 kout%downsampling(:) = kin%downsampling(:)
1083 if (
allocated(kin%coord_along_path))
then
1084 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1085 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1088 if (
allocated(kin%symmetry_ops))
then
1089 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1090 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1091 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1092 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1093 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1101 integer pure function kpoints_number(this) result(number)
1104 number = this%reduced%npoints
1112 integer,
intent(in) :: ik
1113 logical,
optional,
intent(in) :: absolute_coordinates
1114 real(real64) :: point(1:this%full%dim)
1116 if (optional_default(absolute_coordinates, .
true.))
then
1117 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1119 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1126 real(real64)
pure function kpoints_get_weight(this, ik) result(weight)
1128 integer,
intent(in) :: ik
1130 weight = this%reduced%weight(ik)
1138 integer,
intent(in) :: ik
1140 equiv = this%reduced%equiv(ik)
1154 integer,
intent(in) :: dim
1155 integer,
intent(in) :: naxis(1:dim)
1156 integer,
intent(in) :: nshifts
1157 real(real64),
intent(in) :: shift(:, :)
1158 real(real64),
intent(out) :: kpoints(:, :)
1159 integer,
optional,
intent(out) :: lk123(:, :)
1162 real(real64) :: dx(dim)
1163 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1164 integer,
allocatable :: lk123_(:, :), idx(:)
1168 dx = m_one/(m_two*naxis)
1170 npoints = product(naxis)
1172 safe_allocate(idx(1:npoints*nshifts))
1173 if (
present(lk123))
then
1174 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1178 do ii = 0, npoints - 1
1179 ik = npoints*is - ii
1184 divisor = divisor / naxis(idir)
1185 ix(idir) = jj / divisor + 1
1186 jj = mod(jj, divisor)
1188 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1192 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64)
then
1193 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1197 if (
present(lk123))
then
1206 if (
present(lk123))
then
1207 do ik = 1, npoints*nshifts
1208 lk123(ik,:) = lk123_(idx(ik),:)
1210 safe_deallocate_a(lk123_)
1213 safe_deallocate_a(idx)
1228 integer,
intent(in ) :: nik_axis(:)
1229 real(real64),
intent(inout) :: kpoints(:, :)
1232 integer,
optional,
intent(in) :: nshifts
1233 integer,
optional,
intent(out) :: indices(:)
1236 integer :: ndim, nk, ik, nshifts_
1237 real(real64) :: dk(size(kpoints, 1))
1238 integer,
allocatable :: idx(:)
1239 real(real64),
allocatable :: shell(:), kpoints_unsorted(:, :)
1243 ndim =
size(kpoints, 1)
1244 nshifts_ = optional_default(nshifts, 1)
1245 nk = product(nik_axis) * nshifts_
1250 dk = m_one / (m_two * nik_axis)
1252 safe_allocate(shell(1:nk))
1253 safe_allocate(idx(1:nk))
1254 safe_allocate_source(kpoints_unsorted(1:ndim, 1:nk), kpoints)
1258 shell(ik) = sum((kpoints_unsorted(:, ik) / dk)**2)
1261 call robust_sort_by_abs(shell, kpoints_unsorted, idx)
1262 safe_deallocate_a(shell)
1265 kpoints(:, ik) = kpoints_unsorted(:, idx(ik))
1268 if (
present(indices)) indices = idx
1270 safe_deallocate_a(idx)
1271 safe_deallocate_a(kpoints_unsorted)
1279 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1280 integer,
intent(in) :: dim
1281 type(lattice_vectors_t),
intent(in) :: latt
1282 integer,
intent(in) :: nkpoints
1283 integer,
intent(in) :: nsegments
1284 integer,
intent(in) :: resolution(:)
1285 real(real64),
intent(in) :: highsympoints(:,:)
1286 real(real64),
intent(out) :: kpoints(1:dim, 1:nkpoints)
1287 real(real64),
intent(out) :: coord(1:nkpoints)
1289 integer :: is, ik, kpt_ind
1290 real(real64) :: length, total_length, accumulated_length
1291 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1295 total_length = m_zero
1296 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1298 do is = 1, nsegments
1305 if (resolution(is) > 0) total_length = total_length + length
1308 accumulated_length = m_zero
1311 do is = 1, nsegments
1320 do ik = 1, resolution(is)
1321 kpt_ind = kpt_ind +1
1322 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1323 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1325 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1328 kpt_ind = kpt_ind +1
1330 coord(kpt_ind) = accumulated_length
1331 kpoints(:, kpt_ind) = kpt1
1334 coord = coord/total_length
1341 subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, equiv, symm_ops, num_symm_ops)
1342 type(symmetries_t),
intent(in) :: symm
1343 logical,
intent(in) :: time_reversal
1344 integer,
intent(inout) :: nkpoints
1345 integer,
intent(in) :: dim
1346 real(real64),
intent(inout) :: kpoints(1:dim,1:nkpoints)
1347 real(real64),
intent(out) :: weights(1:nkpoints)
1348 integer,
intent(out) :: equiv(1:nkpoints)
1349 integer,
intent(out) :: symm_ops(:, :)
1350 integer,
intent(out) :: num_symm_ops(:)
1353 real(real64),
allocatable :: reduced(:, :)
1355 integer ik, iop, ik2
1356 real(real64) :: tran(dim), diff(dim)
1357 real(real64),
allocatable :: kweight(:)
1359 real(real64) :: prec
1366 prec = min(symprec, m_one/(nkpoints*100))
1373 safe_allocate(kweight(1:nkpoints))
1374 safe_allocate(reduced(1:dim, 1:nkpoints))
1376 kweight = m_one / nkpoints
1382 symm_ops(:, 1) = symmetries_identity_index(symm)
1385 if (kweight(ik) < prec) cycle
1389 nreduced = nreduced + 1
1390 reduced(:, nreduced) = kpoints(:, ik)
1391 equiv(ik) = nreduced
1394 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1396 if (ik == nkpoints) cycle
1399 do iop = 1, symmetries_number(symm)
1400 if (iop == symmetries_identity_index(symm) .and. &
1401 .not. time_reversal) cycle
1403 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1405 tran = tran - anint(tran + m_half*prec)
1408 do ik2 = ik + 1, nkpoints
1409 if (kweight(ik2) < prec) cycle
1411 if (.not. iop == symmetries_identity_index(symm))
then
1412 diff = tran - kpoints(:, ik2)
1413 diff = diff - anint(diff)
1416 if (sum(abs(diff)) < prec)
then
1417 kweight(ik) = kweight(ik) + kweight(ik2)
1418 kweight(ik2) = m_zero
1419 equiv(ik2) = nreduced
1420 weights(nreduced) = kweight(ik)
1421 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1422 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1427 if (time_reversal)
then
1428 diff = tran + kpoints(:, ik2)
1429 diff = diff - anint(diff)
1432 if (sum(abs(diff)) < prec)
then
1433 kweight(ik) = kweight(ik) + kweight(ik2)
1434 kweight(ik2) = m_zero
1435 equiv(ik2) = nreduced
1436 weights(nreduced) = kweight(ik)
1437 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1439 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1446 assert(sum(weights(1:nreduced)) - m_one < prec)
1447 assert(all(1 <= equiv(:)) .and. all(equiv(:) <= nreduced))
1451 kpoints(:, ik) = reduced(:, ik)
1454 safe_deallocate_a(kweight)
1455 safe_deallocate_a(reduced)
1464 type(lattice_vectors_t),
intent(in) :: latt
1466 integer :: ig1, ig2, ik
1467 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1468 real(real64) :: vec(grid%dim), kpt(grid%dim)
1469 real(real64) :: d, dmin
1474 do ig1 = 1, grid%dim
1475 do ig2 = 1, 3**grid%dim
1476 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1480 do ig1 = 1, 3**grid%dim
1484 do ik = 1, grid%npoints
1487 do ig1 = 1, 3**grid%dim
1488 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1489 d = real(sum(vec**2), real32)
1496 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1507 integer,
optional,
intent(in) :: iunit
1508 type(namespace_t),
optional,
intent(in) :: namespace
1509 logical,
optional,
intent(in) :: absolute_coordinates
1512 character(len=100) :: str_tmp
1517 call messages_print_with_emphasis(
'Brillouin zone sampling', iunit, namespace)
1521 call messages_write(
'Dimensions of the k-point grid =')
1522 do idir = 1, this%full%dim
1523 call messages_write(this%nik_axis(idir), fmt =
'(i3,1x)')
1525 call messages_new_line()
1527 if (.not. all(this%downsampling(1:this%full%dim) == 1))
then
1528 call messages_write(
'Dimensions of the q-point grid =')
1529 do idir = 1, this%full%dim
1530 call messages_write(this%niq_axis(idir), fmt =
'(i3,1x)')
1532 call messages_new_line()
1535 call messages_write(
'Total number of k-points =')
1536 call messages_write(this%full%npoints)
1537 call messages_new_line()
1539 call messages_write(
'Number of symmetry-reduced k-points =')
1540 call messages_write(this%reduced%npoints)
1542 call messages_info(iunit=iunit, namespace=namespace)
1546 call messages_write(
'Total number of k-points =')
1547 call messages_write(this%full%npoints)
1548 call messages_new_line()
1549 call messages_info(iunit=iunit, namespace=namespace)
1553 call messages_new_line()
1554 call messages_write(
'List of k-points:')
1555 call messages_info(iunit=iunit, namespace=namespace)
1557 write(message(1),
'(6x,a)')
'ik'
1558 do idir = 1, this%full%dim
1559 index = index2axis(idir)
1560 write(str_tmp,
'(9x,2a)')
'k_', index
1561 message(1) = trim(message(1)) // trim(str_tmp)
1563 write(str_tmp,
'(6x,a)')
'Weight'
1564 message(1) = trim(message(1)) // trim(str_tmp)
1565 message(2) =
'---------------------------------------------------------'
1566 call messages_info(2, iunit)
1569 write(message(1),
'(i8,1x)') ik
1570 do idir = 1, this%full%dim
1571 if (optional_default(absolute_coordinates, .false.))
then
1572 write(str_tmp,
'(f12.4)') this%reduced%point(idir, ik)
1574 write(str_tmp,
'(f12.4)') this%reduced%red_point(idir, ik)
1576 message(1) = trim(message(1)) // trim(str_tmp)
1579 message(1) = trim(message(1)) // trim(str_tmp)
1580 call messages_info(1, iunit, namespace=namespace)
1583 call messages_info(iunit=iunit, namespace=namespace)
1585 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1594 integer,
intent(in) :: ik
1602 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1604 integer,
intent(in) :: ik
1606 if (this%use_symmetries)
then
1607 num = this%num_symmetry_ops(ik)
1615 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1617 integer,
intent(in) :: ik
1618 integer,
intent(in) :: index
1620 if (this%use_symmetries)
then
1621 iop = this%symmetry_ops(ik, index)
1629 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1631 integer,
intent(in) :: ik
1632 integer,
intent(in) :: index
1637 if (this%use_symmetries)
then
1638 do iop = 1, this%num_symmetry_ops(ik)
1639 if (this%symmetry_ops(ik, iop) == index)
then
1655 integer :: denom, nik, nik_skip
1659 nik = this%full%npoints
1660 nik_skip = this%nik_skip
1667 do denom = 1, 100000
1668 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1669 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon))
then
1680 logical pure function kpoints_have_zero_weight_path(this) result(have_zerow)
1683 if (this%nik_skip > 0)
then
1686 have_zerow = .false.
1701 integer,
intent(in) :: ind
1703 coord = this%coord_along_path(ind)
1711 type(symmetries_t),
intent(in) :: symm
1712 integer,
intent(in) :: dim
1713 logical,
intent(in) :: time_reversal
1714 type(namespace_t),
intent(in) :: namespace
1716 integer,
allocatable :: kmap(:)
1717 real(real64) :: kpt(dim), diff(dim)
1718 integer :: nk, ik, ik2, iop
1719 type(distributed_t) :: kpt_dist
1726 call distributed_nullify(kpt_dist, nk)
1728 if (mpi_world%comm /= mpi_comm_undefined)
then
1729 call distributed_init(kpt_dist, nk, mpi_comm_world,
"kpt_check")
1734 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1736 do iop = 1, symmetries_number(symm)
1737 if (iop == symmetries_identity_index(symm) .and. &
1738 .not. time_reversal) cycle
1740 do ik = kpt_dist%start, kpt_dist%end
1744 do ik = kpt_dist%start, kpt_dist%end
1746 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1748 kpt = kpt - anint(kpt + m_half*symprec)
1753 if (iop /= symmetries_identity_index(symm))
then
1754 diff = kpt - grid%red_point(:, ik2)
1755 diff = diff - anint(diff)
1757 if (sum(abs(diff)) < symprec)
then
1763 if (time_reversal)
then
1764 diff = kpt + grid%red_point(:, ik2)
1765 diff = diff - anint(diff)
1767 if (sum(abs(diff)) < symprec)
then
1775 if (kmap(ik) == ik)
then
1776 write(message(1),
'(a,i5,a2,3(f7.3,a2),a)')
"The reduced k-point ", ik,
" (", &
1777 grid%red_point(1, ik),
", ", grid%red_point(2, ik),
", ", grid%red_point(3, ik), &
1778 ") ",
"has no symmetric in the k-point grid for the following symmetry"
1779 write(message(2),
'(i5,1x,a,2x,3(3i4,2x))') iop,
':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1780 message(3) =
"Change your k-point grid or use KPointsUseSymmetries=no."
1781 call messages_fatal(3, namespace=namespace)
1786 safe_deallocate_a(kmap)
1788 call distributed_end(kpt_dist)
1796 integer,
intent(in) :: ik
1797 integer,
intent(in) :: iq
1799 integer :: dim, idim
1800 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1805 dim = kpt%reduced%dim
1808 if (all(kpt%downsampling == 1))
then
1815 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1818 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1819 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1820 if (abs(red(idim) - anint(red(idim))) > m_epsilon)
then
1821 compatible = .false.
1835 if (
allocated(this%coord_along_path))
then
1836 npath =
SIZE(this%coord_along_path)
1855 type(lattice_vectors_t),
intent(in) :: new_latt
1861 this%latt = new_latt
1863 do ik = 1, this%reduced%npoints
1864 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1867 do ik = 1, this%full%npoints
real(real64), parameter, public m_zero
real(real64), parameter, public m_half
real(real64), parameter, public m_one
integer pure function kpoints_get_kpoint_method(this)
subroutine, public kpoints_grid_generate(dim, naxis, nshifts, shift, kpoints, lk123)
Generates the k-points grid.
subroutine, public kpoints_end(this)
logical pure function kpoints_have_zero_weight_path(this)
subroutine kpoints_check_symmetries(grid, symm, dim, time_reversal, namespace)
integer, parameter, public kpoints_monkh_pack
subroutine, public kpoints_deterministic_sort(nik_axis, kpoints, nshifts, indices)
Reorder a Monkhorst-Pack grid into a reproducible shell-based ordering.
integer pure function, public kpoints_get_num_symmetry_ops(this, ik)
subroutine kpoints_grid_addto(this, that)
real(real64) pure function, public kpoints_get_path_coord(this, ind)
subroutine, public kpoints_read_user_kpoints(this, namespace, dim)
Read explicit user-defined k-points and append them to the current grids.
integer pure function kpoints_get_equiv(this, ik)
logical pure function, public kpoints_is_valid_symmetry(this, ik, index)
integer function, public kpoints_kweight_denominator(this)
subroutine, public kpoints_copy(kin, kout)
subroutine, public kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
Generate the k-point along a path.
integer, parameter, public kpoints_path
subroutine kpoints_print_info(this, namespace)
pure real(real64) function, dimension(1:this%full%dim) kpoints_get_point(this, ik, absolute_coordinates)
integer function, public kpoints_nkpt_in_path(this)
logical function, public kpoints_is_compatible_downsampling(kpt, ik, iq)
real(real64) pure function kpoints_get_weight(this, ik)
integer function kpoints_set_method(namespace, use_symmetries, only_gamma)
Determine the k-point input method bitmask from the parsed input settings.
integer pure function, public kpoints_get_symmetry_ops(this, ik, index)
subroutine, public kpoints_read_path(this, namespace, dim)
Read the k-points path information and generate the k-points list.
subroutine kpoints_grid_copy(bb, aa)
subroutine, public kpoints_fold_to_1bz(grid, latt)
subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, equiv, symm_ops, num_symm_ops)
subroutine, public kpoints_init(this, namespace, symm, dim, periodic_dim, latt)
subroutine, public kpoints_grid_end(this)
logical pure function, public kpoints_point_is_gamma(this, ik)
subroutine, public kpoints_read_mp(this, namespace, symm, dim, gamma_only)
Read a Monkhorst-Pack k-point grid and initialize the base k-point data.
integer, parameter, public kpoints_user
logical function kpoints_gamma_only(this)
subroutine, public kpoints_lattice_vectors_update(this, new_latt)
subroutine, public kpoints_to_reduced(latt, kin, kout)
subroutine, public kpoints_allocate_and_init(this, symm, dim, latt)
Allocate and initialise attributes that do not depend on parsed quantities.
integer pure function, public kpoints_number(this)
subroutine, public kpoints_to_absolute(latt, kin, kout)
subroutine, public kpoints_grid_init(dim, this, npoints, nshifts)
subroutine kpoints_write_info(this, iunit, namespace, absolute_coordinates)
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
logical function, public parse_is_defined(namespace, name)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
This module is intended to contain "only mathematical" functions and procedures.
integer pure function, public symmetries_number(this)
logical pure function, public symmetries_have_break_dir(this)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
This module is intended to contain simple general-purpose utility functions and procedures.