25 use,
intrinsic :: iso_fortran_env
70 real(real64),
allocatable :: point(:, :)
71 real(real64),
allocatable :: point1BZ(:, :)
72 real(real64),
allocatable :: red_point(:, :)
73 real(real64),
allocatable :: weight(:)
74 integer,
allocatable :: equiv(:)
75 integer :: nshifts = 1
76 real(real64),
allocatable :: shifts(:, :)
77 integer :: npoints = 0
84 type(lattice_vectors_t) :: latt
86 type(kpoints_grid_t) :: full
87 type(kpoints_grid_t) :: reduced
88 type(simplex_t),
pointer :: simplex
92 logical :: use_symmetries = .false.
93 logical :: use_time_reversal = .false.
94 integer :: nik_skip = 0
97 integer,
allocatable :: nik_axis(:)
98 integer,
allocatable :: niq_axis(:)
99 integer,
allocatable,
private :: symmetry_ops(:, :)
100 integer,
allocatable,
private :: num_symmetry_ops(:)
103 real(real64),
allocatable,
private :: coord_along_path(:)
105 integer,
allocatable :: downsampling(:)
107 type(symmetries_t),
pointer :: symm => null()
120 integer,
public,
parameter :: &
130 integer,
intent(in) :: dim
131 type(kpoints_grid_t),
intent(out) :: this
132 integer,
intent(in) :: npoints
133 integer,
intent(in) :: nshifts
138 this%npoints = npoints
139 this%nshifts = nshifts
140 safe_allocate(this%red_point(1:dim, 1:npoints))
141 safe_allocate(this%point(1:dim, 1:npoints))
142 safe_allocate(this%point1bz(1:dim,1:npoints))
143 safe_allocate(this%weight(1:npoints))
144 safe_allocate(this%equiv(1:npoints))
145 safe_allocate(this%shifts(1:dim,1:nshifts))
152 type(kpoints_grid_t),
intent(inout) :: this
156 safe_deallocate_a(this%red_point)
157 safe_deallocate_a(this%point)
158 safe_deallocate_a(this%point1BZ)
159 safe_deallocate_a(this%weight)
160 safe_deallocate_a(this%equiv)
161 safe_deallocate_a(this%shifts)
175 aa%weight(1:bb%npoints) = bb%weight(1:bb%npoints)
176 aa%equiv(1:bb%npoints) = bb%equiv(1:bb%npoints)
177 aa%point(1:bb%dim, 1:bb%npoints) = bb%point(1:bb%dim, 1:bb%npoints)
178 aa%point1BZ(1:bb%dim, 1:bb%npoints) = bb%point1BZ(1:bb%dim, 1:bb%npoints)
179 aa%red_point(1:bb%dim, 1:bb%npoints) = bb%red_point(1:bb%dim, 1:bb%npoints)
180 aa%shifts(1:bb%dim, 1:bb%nshifts) = bb%shifts(1:bb%dim, 1:bb%nshifts)
194 if (.not.
allocated(that%point))
then
199 if (.not.
allocated(this%point))
then
217 this%red_point(1:old_grid%dim, 1:old_grid%npoints)= old_grid%red_point(1:old_grid%dim, 1:old_grid%npoints)
218 this%point(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point(1:old_grid%dim, 1:old_grid%npoints)
219 this%point1BZ(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point1BZ(1:old_grid%dim, 1:old_grid%npoints)
220 this%weight(1:old_grid%npoints) = old_grid%weight(1:old_grid%npoints)
221 this%equiv(1:old_grid%npoints) = old_grid%equiv(1:old_grid%npoints)
222 this%shifts(1:old_grid%dim, 1:old_grid%nshifts) = old_grid%shifts(1:old_grid%dim, 1:old_grid%nshifts)
225 this%red_point(1:old_grid%dim, old_grid%npoints+1:this%npoints)= that%red_point(1:that%dim, 1:that%npoints)
226 this%point(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point(1:that%dim, 1:that%npoints)
227 this%point1BZ(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point1BZ(1:that%dim, 1:that%npoints)
228 this%weight(old_grid%npoints+1:this%npoints) = that%weight(1:that%npoints)
229 this%equiv(old_grid%npoints+1:this%npoints) = that%equiv(1:that%npoints)
238 subroutine kpoints_init(this, namespace, symm, dim, periodic_dim, latt)
242 integer,
intent(in) :: dim
243 integer,
intent(in) :: periodic_dim
246 integer :: ik, idir, is
247 character(len=100) :: str_tmp
248 real(real64) :: weight_sum
249 logical :: default_timereversal, only_gamma
255 safe_allocate(this%nik_axis(1:dim))
256 safe_allocate(this%niq_axis(1:dim))
257 safe_allocate(this%downsampling(1:dim))
261 only_gamma = (periodic_dim == 0)
265 this%simplex => null()
284 call parse_variable(namespace,
'KPointsUseSymmetries', .false., this%use_symmetries)
304 call parse_variable(namespace,
'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
310 this%method = kpoints_gamma
320 call read_mp(gamma_only = .false.)
327 if (this%use_symmetries)
then
328 write(
message(1),
'(a)')
"User-defined k-points are not compatible with KPointsUseSymmetries=yes."
339 if (this%use_symmetries)
then
340 write(
message(1),
'(a)')
"KPointsPath is not compatible with KPointsUseSymmetries=yes."
347 if (this%method == 0)
then
348 write(
message(1),
'(a)')
"Unable to determine the method for defining k-points."
349 write(
message(2),
'(a)')
"Octopus will continue assuming a Monkhorst Pack grid."
352 call read_mp(gamma_only = .false.)
359 write(
message(2),
'(1x,i5,a)') this%reduced%npoints,
' k-points generated from parameters :'
360 write(
message(3),
'(1x,a)')
'---------------------------------------------------'
361 write(
message(4),
'(4x,a)')
'n ='
363 write(str_tmp,
'(i5)') this%nik_axis(idir)
368 do is = 1, this%reduced%nshifts
370 write(
message(2),
'(4x,a,i1,a)')
's', is,
' ='
372 write(str_tmp,
'(f6.2)') this%reduced%shifts(idir,is)
380 write(
message(2),
'(a)')
' index | weight | coordinates |'
383 do ik = 1, this%reduced%npoints
384 write(str_tmp,
'(i8,a,f12.6,a)') ik,
" | ", this%reduced%weight(ik),
" |"
387 write(str_tmp,
'(f12.6)') this%reduced%red_point(idir, ik)
390 write(str_tmp,
'(a)')
" |"
404 logical,
intent(in) :: gamma_only
406 logical :: gamma_only_
407 integer :: ii, is, ncols, nshifts
409 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
410 real(real64),
allocatable :: shifts(:, :)
411 integer(int64) :: dos_method
460 gamma_only_ = gamma_only
461 if (.not. gamma_only_)
then
462 gamma_only_ = (
parse_block(namespace,
'KPointsGrid', blk) /= 0)
467 if (.not. gamma_only_)
then
472 safe_allocate(shifts(1:dim,1:nshifts))
475 if (.not. gamma_only_)
then
477 if (ncols /= dim)
then
478 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid first row has ', ncols,
' columns but should have ', dim
479 if (ncols < dim)
then
482 write(
message(2),
'(a)')
'Continuing, but ignoring the additional values.'
490 if (any(this%nik_axis < 1))
then
491 message(1) =
'Input: KPointsGrid is not valid.'
497 if (ncols /= dim)
then
498 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid shift has ', ncols,
' columns but must have ', dim
509 if (mod(this%nik_axis(ii), 2) /= 0)
then
539 this%niq_axis(:) = this%nik_axis(:)
540 this%downsampling(:) = 1
542 if (
parse_block(namespace,
'QPointsGrid', blk) == 0)
then
544 if (ncols /= dim)
then
545 write(
message(1),
'(a,i3,a,i3)')
'QPointsGrid first row has ', ncols,
' columns but must have ', dim
552 if (any(this%nik_axis/this%niq_axis /= nint(this%nik_axis/real(this%niq_axis))))
then
553 message(1) =
'Input: QPointsGrid is not compatible with the KPointsGrid.'
557 this%downsampling = this%nik_axis/this%niq_axis
559 if (any(this%downsampling /= 1))
then
570 this%full%shifts(:, :) = shifts(:, :)
571 safe_deallocate_a(shifts)
573 call kpoints_grid_generate(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point)
575 do ik = 1, this%full%npoints
579 this%full%weight =
m_one / this%full%npoints
582 do ik = 1, this%full%npoints
583 this%full%equiv(ik) = ik
586 if (this%use_symmetries)
then
587 message(1) =
"Checking if the generated full k-point grid is symmetric"
595 if (this%use_symmetries)
then
597 safe_allocate(num_symm_ops(1:this%full%npoints))
599 if (this%use_time_reversal)
then
606 this%reduced%npoints, dim, this%reduced%red_point, this%reduced%weight, this%reduced%equiv, symm_ops, num_symm_ops)
609 assert(maxval(num_symm_ops) >= 1)
610 if (this%use_time_reversal)
then
616 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
618 do ik = 1, this%reduced%npoints
619 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
622 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)))
623 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
625 this%num_symmetry_ops(1:this%reduced%npoints) = num_symm_ops(1:this%reduced%npoints)
626 this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)) = &
627 symm_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops))
629 safe_deallocate_a(num_symm_ops)
630 safe_deallocate_a(symm_ops)
634 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
635 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1))
636 this%num_symmetry_ops(1:this%reduced%npoints) = 1
637 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
641 do ik = 1, this%reduced%npoints
642 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
648 call parse_variable(namespace,
'DOSMethod', option__dosmethod__smear, dos_method)
649 if (dos_method == option__dosmethod__tetrahedra)
then
650 this%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, this%reduced%equiv)
660 integer :: nshifts, nkpoints, nhighsympoints, nsegments
661 integer :: icol, ik, idir, ncols
662 integer,
allocatable :: resolution(:)
663 real(real64),
allocatable :: highsympoints(:, :)
667 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
696 if (
parse_block(namespace,
'KPointsPath', blk) /= 0)
then
697 write(
message(1),
'(a)')
'Internal error while reading KPointsPath.'
704 if (nhighsympoints /= nsegments + 1)
then
705 write(
message(1),
'(a,i3,a,i3)')
'The first row of KPointsPath is not compatible with the number of specified k-points.'
709 safe_allocate(resolution(1:nsegments))
710 do icol = 1, nsegments
714 nkpoints = sum(resolution) + 1
716 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
717 do ik = 1, nhighsympoints
720 if (ncols /= dim)
then
721 write(
message(1),
'(a,i8,a,i3,a,i3)')
'KPointsPath row ', ik,
' has ', ncols,
' columns but must have ', dim
737 safe_allocate(this%coord_along_path(1:nkpoints))
739 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
740 this%coord_along_path)
742 safe_deallocate_a(resolution)
743 safe_deallocate_a(highsympoints)
748 path_kpoints_grid%weight =
m_one/path_kpoints_grid%npoints
750 path_kpoints_grid%weight =
m_zero
751 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
756 do ik = 1, path_kpoints_grid%npoints
757 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
764 if (
allocated(this%symmetry_ops))
then
765 npoints = this%reduced%npoints
766 safe_allocate(num_symm_ops(1:npoints))
767 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
769 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
770 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
771 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
777 if (
allocated(this%symmetry_ops))
then
778 safe_deallocate_a(this%num_symmetry_ops)
779 safe_deallocate_a(this%symmetry_ops)
780 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
781 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
783 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
784 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
785 symm_ops(1:npoints, 1:maxval(num_symm_ops))
786 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
787 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
789 safe_deallocate_a(num_symm_ops)
790 safe_deallocate_a(symm_ops)
791 else if(this%use_symmetries)
then
792 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
793 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
795 this%num_symmetry_ops(1:this%reduced%npoints) = 1
796 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
847 if (
parse_block(namespace,
'KPoints', blk) /= 0)
then
848 if (
parse_block(namespace,
'KPointsReduced', blk) == 0)
then
852 write(
message(1),
'(a)')
'Internal error loading user-defined k-point list.'
862 user_kpoints_grid%red_point =
m_zero
863 user_kpoints_grid%point =
m_zero
864 user_kpoints_grid%weight =
m_zero
865 user_kpoints_grid%equiv = 0
866 user_kpoints_grid%shifts =
m_zero
870 do ik = 1, user_kpoints_grid%npoints
876 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
879 do ik = 1, user_kpoints_grid%npoints
885 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
891 if (any(user_kpoints_grid%weight <
m_epsilon))
then
893 message(1) =
"Found k-points with zero weight. They are excluded from density calculation"
899 do ik=1,user_kpoints_grid%npoints
900 if (user_kpoints_grid%weight(ik) <
m_epsilon)
then
902 if (ik < user_kpoints_grid%npoints)
then
903 if (user_kpoints_grid%weight(ik+1) >
m_epsilon)
then
904 message(1) =
"K-points with zero weight must follow all regular k-points in a block"
908 this%nik_skip = this%nik_skip + 1
910 user_kpoints_grid%weight(ik) =
m_zero
915 weight_sum = sum(user_kpoints_grid%weight)
917 message(1) =
"k-point weights must sum to a positive number."
920 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
931 write(
message(1),
'(a,i4,a)')
'Input: ', user_kpoints_grid%npoints,
' k-points were read from the input file'
950 safe_deallocate_a(this%nik_axis)
951 safe_deallocate_a(this%niq_axis)
952 safe_deallocate_a(this%downsampling)
953 safe_deallocate_a(this%symmetry_ops)
954 safe_deallocate_a(this%num_symmetry_ops)
955 safe_deallocate_a(this%coord_along_path)
956 safe_deallocate_p(this%simplex)
964 real(real64),
intent(in) :: kin(:)
965 real(real64),
intent(out) :: kout(:)
969 kout = matmul(latt%klattice, kin)
977 real(real64),
intent(in) :: kin(:)
978 real(real64),
intent(out) :: kout(:)
982 kout = matmul(kin, latt%rlattice) / (
m_two*
m_pi)
997 kout%method = kin%method
1002 kout%use_symmetries = kin%use_symmetries
1003 kout%use_time_reversal = kin%use_time_reversal
1005 safe_allocate(kout%nik_axis(1:kin%full%dim))
1006 safe_allocate(kout%niq_axis(1:kin%full%dim))
1007 safe_allocate(kout%downsampling(1:kin%full%dim))
1008 kout%nik_axis(:) = kin%nik_axis(:)
1009 kout%niq_axis(:) = kin%niq_axis(:)
1010 kout%downsampling(:) = kin%downsampling(:)
1012 if (
allocated(kin%coord_along_path))
then
1013 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1014 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1017 if (
allocated(kin%symmetry_ops))
then
1018 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1019 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1020 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1021 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1022 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1030 integer pure function kpoints_number(this) result(number)
1033 number = this%reduced%npoints
1041 integer,
intent(in) :: ik
1042 logical,
optional,
intent(in) :: absolute_coordinates
1043 real(real64) :: point(1:this%full%dim)
1045 if (optional_default(absolute_coordinates, .
true.))
then
1046 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1048 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1057 integer,
intent(in) :: ik
1059 weight = this%reduced%weight(ik)
1067 integer,
intent(in) :: ik
1069 equiv = this%reduced%equiv(ik)
1083 integer,
intent(in) :: dim
1084 integer,
intent(in) :: naxis(1:dim)
1085 integer,
intent(in) :: nshifts
1086 real(real64),
intent(in) :: shift(:, :)
1087 real(real64),
intent(out) :: kpoints(:, :)
1088 integer,
optional,
intent(out) :: lk123(:, :)
1091 real(real64) :: dx(dim), maxcoord
1092 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1093 integer,
allocatable :: lk123_(:, :), idx(:)
1094 real(real64),
allocatable :: nrm(:), shell(:), coords(:, :)
1098 dx = m_one/(m_two*naxis)
1100 npoints = product(naxis)
1102 if (
present(lk123))
then
1103 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1104 safe_allocate(idx(1:npoints*nshifts))
1108 do ii = 0, npoints - 1
1109 ik = npoints*is - ii
1114 divisor = divisor / naxis(idir)
1115 ix(idir) = jj / divisor + 1
1116 jj = mod(jj, divisor)
1118 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1122 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64)
then
1123 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1127 if (
present(lk123))
then
1136 safe_allocate(nrm(1:npoints*nshifts))
1137 safe_allocate(shell(1:npoints*nshifts))
1138 safe_allocate(coords(1:dim, 1:npoints*nshifts))
1140 do ik = 1, npoints*nshifts
1141 shell(ik) = sum((kpoints(:, ik)/dx)**2)
1143 coords(idir, ik) = kpoints(idir, ik)
1144 if (coords(idir, ik) < m_zero) coords(idir, ik) = coords(idir, ik) + m_one
1145 coords(idir, ik) = coords(idir, ik)/(dx(idir)*m_two)
1153 do ik = 1, npoints*nshifts
1154 nrm(ik) = nrm(ik) + coords(idir, ik)*maxcoord
1156 maxcoord = maxcoord*max(m_one, maxval(coords(idir, 1:npoints*nshifts)))
1159 do ik = 1, npoints*nshifts
1160 nrm(ik) = nrm(ik) + shell(ik)*maxcoord
1163 if (
present(lk123))
then
1165 kpoints(:,:) = kpoints(:,idx)
1166 do ik = 1, npoints*nshifts
1167 lk123(ik,:) = lk123_(idx(ik),:)
1169 safe_deallocate_a(lk123_)
1170 safe_deallocate_a(idx)
1172 call sort(nrm, kpoints)
1175 safe_deallocate_a(nrm)
1176 safe_deallocate_a(shell)
1177 safe_deallocate_a(coords)
1184 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1185 integer,
intent(in) :: dim
1186 type(lattice_vectors_t),
intent(in) :: latt
1187 integer,
intent(in) :: nkpoints
1188 integer,
intent(in) :: nsegments
1189 integer,
intent(in) :: resolution(:)
1190 real(real64),
intent(in) :: highsympoints(:,:)
1191 real(real64),
intent(out) :: kpoints(1:dim, 1:nkpoints)
1192 real(real64),
intent(out) :: coord(1:nkpoints)
1194 integer :: is, ik, kpt_ind
1195 real(real64) :: length, total_length, accumulated_length
1196 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1200 total_length = m_zero
1201 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1203 do is = 1, nsegments
1210 if (resolution(is) > 0) total_length = total_length + length
1213 accumulated_length = m_zero
1216 do is = 1, nsegments
1225 do ik = 1, resolution(is)
1226 kpt_ind = kpt_ind +1
1227 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1228 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1230 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1233 kpt_ind = kpt_ind +1
1235 coord(kpt_ind) = accumulated_length
1236 kpoints(:, kpt_ind) = kpt1
1239 coord = coord/total_length
1246 subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, equiv, symm_ops, num_symm_ops)
1247 type(symmetries_t),
intent(in) :: symm
1248 logical,
intent(in) :: time_reversal
1249 integer,
intent(inout) :: nkpoints
1250 integer,
intent(in) :: dim
1251 real(real64),
intent(inout) :: kpoints(1:dim,1:nkpoints)
1252 real(real64),
intent(out) :: weights(1:nkpoints)
1253 integer,
intent(out) :: equiv(1:nkpoints)
1254 integer,
intent(out) :: symm_ops(:, :)
1255 integer,
intent(out) :: num_symm_ops(:)
1258 real(real64),
allocatable :: reduced(:, :)
1260 integer ik, iop, ik2
1261 real(real64) :: tran(dim), diff(dim)
1262 real(real64),
allocatable :: kweight(:)
1264 real(real64) :: prec
1271 prec = min(symprec, m_one/(nkpoints*100))
1278 safe_allocate(kweight(1:nkpoints))
1279 safe_allocate(reduced(1:dim, 1:nkpoints))
1281 kweight = m_one / nkpoints
1287 symm_ops(:, 1) = symmetries_identity_index(symm)
1290 if (kweight(ik) < prec) cycle
1294 nreduced = nreduced + 1
1295 reduced(:, nreduced) = kpoints(:, ik)
1296 equiv(ik) = nreduced
1299 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1301 if (ik == nkpoints) cycle
1304 do iop = 1, symmetries_number(symm)
1305 if (iop == symmetries_identity_index(symm) .and. &
1306 .not. time_reversal) cycle
1308 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1310 tran = tran - anint(tran + m_half*prec)
1313 do ik2 = ik + 1, nkpoints
1314 if (kweight(ik2) < prec) cycle
1316 if (.not. iop == symmetries_identity_index(symm))
then
1317 diff = tran - kpoints(:, ik2)
1318 diff = diff - anint(diff)
1321 if (sum(abs(diff)) < prec)
then
1322 kweight(ik) = kweight(ik) + kweight(ik2)
1323 kweight(ik2) = m_zero
1324 equiv(ik2) = nreduced
1325 weights(nreduced) = kweight(ik)
1326 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1327 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1332 if (time_reversal)
then
1333 diff = tran + kpoints(:, ik2)
1334 diff = diff - anint(diff)
1337 if (sum(abs(diff)) < prec)
then
1338 kweight(ik) = kweight(ik) + kweight(ik2)
1339 kweight(ik2) = m_zero
1340 equiv(ik2) = nreduced
1341 weights(nreduced) = kweight(ik)
1342 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1344 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1351 assert(sum(weights(1:nreduced)) - m_one < prec)
1352 assert(all(1 <= equiv(:)) .and. all(equiv(:) <= nreduced))
1356 kpoints(:, ik) = reduced(:, ik)
1359 safe_deallocate_a(kweight)
1360 safe_deallocate_a(reduced)
1369 type(lattice_vectors_t),
intent(in) :: latt
1371 integer :: ig1, ig2, ik
1372 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1373 real(real64) :: vec(grid%dim), kpt(grid%dim)
1374 real(real64) :: d, dmin
1379 do ig1 = 1, grid%dim
1380 do ig2 = 1, 3**grid%dim
1381 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1385 do ig1 = 1, 3**grid%dim
1389 do ik = 1, grid%npoints
1392 do ig1 = 1, 3**grid%dim
1393 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1394 d = real(sum(vec**2), real32)
1401 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1412 integer,
optional,
intent(in) :: iunit
1413 type(namespace_t),
optional,
intent(in) :: namespace
1414 logical,
optional,
intent(in) :: absolute_coordinates
1417 character(len=100) :: str_tmp
1422 call messages_print_with_emphasis(
'Brillouin zone sampling', iunit, namespace)
1426 call messages_write(
'Dimensions of the k-point grid =')
1427 do idir = 1, this%full%dim
1428 call messages_write(this%nik_axis(idir), fmt =
'(i3,1x)')
1430 call messages_new_line()
1432 if (.not. all(this%downsampling(1:this%full%dim) == 1))
then
1433 call messages_write(
'Dimensions of the q-point grid =')
1434 do idir = 1, this%full%dim
1435 call messages_write(this%niq_axis(idir), fmt =
'(i3,1x)')
1437 call messages_new_line()
1440 call messages_write(
'Total number of k-points =')
1441 call messages_write(this%full%npoints)
1442 call messages_new_line()
1444 call messages_write(
'Number of symmetry-reduced k-points =')
1445 call messages_write(this%reduced%npoints)
1447 call messages_info(iunit=iunit, namespace=namespace)
1451 call messages_write(
'Total number of k-points =')
1452 call messages_write(this%full%npoints)
1453 call messages_new_line()
1454 call messages_info(iunit=iunit, namespace=namespace)
1458 call messages_new_line()
1459 call messages_write(
'List of k-points:')
1460 call messages_info(iunit=iunit, namespace=namespace)
1462 write(message(1),
'(6x,a)')
'ik'
1463 do idir = 1, this%full%dim
1464 index = index2axis(idir)
1465 write(str_tmp,
'(9x,2a)')
'k_', index
1466 message(1) = trim(message(1)) // trim(str_tmp)
1468 write(str_tmp,
'(6x,a)')
'Weight'
1469 message(1) = trim(message(1)) // trim(str_tmp)
1470 message(2) =
'---------------------------------------------------------'
1471 call messages_info(2, iunit)
1474 write(message(1),
'(i8,1x)') ik
1475 do idir = 1, this%full%dim
1476 if (optional_default(absolute_coordinates, .false.))
then
1477 write(str_tmp,
'(f12.4)') this%reduced%point(idir, ik)
1479 write(str_tmp,
'(f12.4)') this%reduced%red_point(idir, ik)
1481 message(1) = trim(message(1)) // trim(str_tmp)
1484 message(1) = trim(message(1)) // trim(str_tmp)
1485 call messages_info(1, iunit, namespace=namespace)
1488 call messages_info(iunit=iunit, namespace=namespace)
1490 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1499 integer,
intent(in) :: ik
1507 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1509 integer,
intent(in) :: ik
1511 if (this%use_symmetries)
then
1512 num = this%num_symmetry_ops(ik)
1520 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1522 integer,
intent(in) :: ik
1523 integer,
intent(in) :: index
1525 if (this%use_symmetries)
then
1526 iop = this%symmetry_ops(ik, index)
1534 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1536 integer,
intent(in) :: ik
1537 integer,
intent(in) :: index
1542 if (this%use_symmetries)
then
1543 do iop = 1, this%num_symmetry_ops(ik)
1544 if (this%symmetry_ops(ik, iop) == index)
then
1560 integer :: denom, nik, nik_skip
1564 nik = this%full%npoints
1565 nik_skip = this%nik_skip
1572 do denom = 1, 100000
1573 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1574 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon))
then
1585 logical pure function kpoints_have_zero_weight_path(this) result(have_zerow)
1588 if (this%nik_skip > 0)
then
1591 have_zerow = .false.
1606 integer,
intent(in) :: ind
1608 coord = this%coord_along_path(ind)
1616 type(symmetries_t),
intent(in) :: symm
1617 integer,
intent(in) :: dim
1618 logical,
intent(in) :: time_reversal
1619 type(namespace_t),
intent(in) :: namespace
1621 integer,
allocatable :: kmap(:)
1622 real(real64) :: kpt(dim), diff(dim)
1623 integer :: nk, ik, ik2, iop
1624 type(distributed_t) :: kpt_dist
1631 call distributed_nullify(kpt_dist, nk)
1633 if (mpi_world%comm /= mpi_comm_undefined)
then
1634 call distributed_init(kpt_dist, nk, mpi_comm_world,
"kpt_check")
1639 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1641 do iop = 1, symmetries_number(symm)
1642 if (iop == symmetries_identity_index(symm) .and. &
1643 .not. time_reversal) cycle
1645 do ik = kpt_dist%start, kpt_dist%end
1649 do ik = kpt_dist%start, kpt_dist%end
1651 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1653 kpt = kpt - anint(kpt + m_half*symprec)
1658 if (iop /= symmetries_identity_index(symm))
then
1659 diff = kpt - grid%red_point(:, ik2)
1660 diff = diff - anint(diff)
1662 if (sum(abs(diff)) < symprec)
then
1668 if (time_reversal)
then
1669 diff = kpt + grid%red_point(:, ik2)
1670 diff = diff - anint(diff)
1672 if (sum(abs(diff)) < symprec)
then
1680 if (kmap(ik) == ik)
then
1681 write(message(1),
'(a,i5,a2,3(f7.3,a2),a)')
"The reduced k-point ", ik,
" (", &
1682 grid%red_point(1, ik),
", ", grid%red_point(2, ik),
", ", grid%red_point(3, ik), &
1683 ") ",
"has no symmetric in the k-point grid for the following symmetry"
1684 write(message(2),
'(i5,1x,a,2x,3(3i4,2x))') iop,
':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1685 message(3) =
"Change your k-point grid or use KPointsUseSymmetries=no."
1686 call messages_fatal(3, namespace=namespace)
1691 safe_deallocate_a(kmap)
1693 call distributed_end(kpt_dist)
1701 integer,
intent(in) :: ik
1702 integer,
intent(in) :: iq
1704 integer :: dim, idim
1705 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1710 dim = kpt%reduced%dim
1713 if (all(kpt%downsampling == 1))
then
1720 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1723 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1724 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1725 if (abs(red(idim) - anint(red(idim))) > m_epsilon)
then
1726 compatible = .false.
1740 if (
allocated(this%coord_along_path))
then
1741 npath =
SIZE(this%coord_along_path)
1760 type(lattice_vectors_t),
intent(in) :: new_latt
1766 this%latt = new_latt
1768 do ik = 1, this%reduced%npoints
1769 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1772 do ik = 1, this%full%npoints
subroutine read_mp(gamma_only)
subroutine read_path()
Read the k-points path information and generate the k-points list.
subroutine read_user_kpoints()
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_epsilon
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
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)
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
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 pure function, public kpoints_get_symmetry_ops(this, ik, index)
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)
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)
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_experimental(name, 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.
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
This module is intended to contain simple general-purpose utility functions and procedures.