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, &
651 this%reduced%equiv, opt = .false.)
652 elseif (dos_method == option__dosmethod__tetrahedra_opt)
then
653 this%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
654 this%reduced%equiv, opt = .
true.)
664 integer :: nshifts, nkpoints, nhighsympoints, nsegments
665 integer :: icol, ik, idir, ncols
666 integer,
allocatable :: resolution(:)
667 real(real64),
allocatable :: highsympoints(:, :)
671 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
700 if (
parse_block(namespace,
'KPointsPath', blk) /= 0)
then
701 write(
message(1),
'(a)')
'Internal error while reading KPointsPath.'
708 if (nhighsympoints /= nsegments + 1)
then
709 write(
message(1),
'(a,i3,a,i3)')
'The first row of KPointsPath is not compatible with the number of specified k-points.'
713 safe_allocate(resolution(1:nsegments))
714 do icol = 1, nsegments
718 nkpoints = sum(resolution) + 1
720 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
721 do ik = 1, nhighsympoints
724 if (ncols /= dim)
then
725 write(
message(1),
'(a,i8,a,i3,a,i3)')
'KPointsPath row ', ik,
' has ', ncols,
' columns but must have ', dim
741 safe_allocate(this%coord_along_path(1:nkpoints))
743 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
744 this%coord_along_path)
746 safe_deallocate_a(resolution)
747 safe_deallocate_a(highsympoints)
752 path_kpoints_grid%weight =
m_one/path_kpoints_grid%npoints
754 path_kpoints_grid%weight =
m_zero
755 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
760 do ik = 1, path_kpoints_grid%npoints
761 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
768 if (
allocated(this%symmetry_ops))
then
769 npoints = this%reduced%npoints
770 safe_allocate(num_symm_ops(1:npoints))
771 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
773 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
774 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
775 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
781 if (
allocated(this%symmetry_ops))
then
782 safe_deallocate_a(this%num_symmetry_ops)
783 safe_deallocate_a(this%symmetry_ops)
784 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
785 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
787 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
788 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
789 symm_ops(1:npoints, 1:maxval(num_symm_ops))
790 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
791 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
793 safe_deallocate_a(num_symm_ops)
794 safe_deallocate_a(symm_ops)
795 else if(this%use_symmetries)
then
796 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
797 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
799 this%num_symmetry_ops(1:this%reduced%npoints) = 1
800 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
851 if (
parse_block(namespace,
'KPoints', blk) /= 0)
then
852 if (
parse_block(namespace,
'KPointsReduced', blk) == 0)
then
856 write(
message(1),
'(a)')
'Internal error loading user-defined k-point list.'
866 user_kpoints_grid%red_point =
m_zero
867 user_kpoints_grid%point =
m_zero
868 user_kpoints_grid%weight =
m_zero
869 user_kpoints_grid%equiv = 0
870 user_kpoints_grid%shifts =
m_zero
874 do ik = 1, user_kpoints_grid%npoints
880 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
883 do ik = 1, user_kpoints_grid%npoints
889 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
895 if (any(user_kpoints_grid%weight <
m_epsilon))
then
897 message(1) =
"Found k-points with zero weight. They are excluded from density calculation"
903 do ik=1,user_kpoints_grid%npoints
904 if (user_kpoints_grid%weight(ik) <
m_epsilon)
then
906 if (ik < user_kpoints_grid%npoints)
then
907 if (user_kpoints_grid%weight(ik+1) >
m_epsilon)
then
908 message(1) =
"K-points with zero weight must follow all regular k-points in a block"
912 this%nik_skip = this%nik_skip + 1
914 user_kpoints_grid%weight(ik) =
m_zero
919 weight_sum = sum(user_kpoints_grid%weight)
921 message(1) =
"k-point weights must sum to a positive number."
924 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
935 write(
message(1),
'(a,i4,a)')
'Input: ', user_kpoints_grid%npoints,
' k-points were read from the input file'
954 safe_deallocate_a(this%nik_axis)
955 safe_deallocate_a(this%niq_axis)
956 safe_deallocate_a(this%downsampling)
957 safe_deallocate_a(this%symmetry_ops)
958 safe_deallocate_a(this%num_symmetry_ops)
959 safe_deallocate_a(this%coord_along_path)
960 safe_deallocate_p(this%simplex)
968 real(real64),
intent(in) :: kin(:)
969 real(real64),
intent(out) :: kout(:)
973 kout = matmul(latt%klattice, kin)
981 real(real64),
intent(in) :: kin(:)
982 real(real64),
intent(out) :: kout(:)
986 kout = matmul(kin, latt%rlattice) / (
m_two*
m_pi)
1001 kout%method = kin%method
1006 kout%use_symmetries = kin%use_symmetries
1007 kout%use_time_reversal = kin%use_time_reversal
1009 safe_allocate(kout%nik_axis(1:kin%full%dim))
1010 safe_allocate(kout%niq_axis(1:kin%full%dim))
1011 safe_allocate(kout%downsampling(1:kin%full%dim))
1012 kout%nik_axis(:) = kin%nik_axis(:)
1013 kout%niq_axis(:) = kin%niq_axis(:)
1014 kout%downsampling(:) = kin%downsampling(:)
1016 if (
allocated(kin%coord_along_path))
then
1017 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1018 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1021 if (
allocated(kin%symmetry_ops))
then
1022 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1023 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1024 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1025 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1026 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1034 integer pure function kpoints_number(this) result(number)
1037 number = this%reduced%npoints
1045 integer,
intent(in) :: ik
1046 logical,
optional,
intent(in) :: absolute_coordinates
1047 real(real64) :: point(1:this%full%dim)
1049 if (optional_default(absolute_coordinates, .
true.))
then
1050 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1052 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1061 integer,
intent(in) :: ik
1063 weight = this%reduced%weight(ik)
1071 integer,
intent(in) :: ik
1073 equiv = this%reduced%equiv(ik)
1087 integer,
intent(in) :: dim
1088 integer,
intent(in) :: naxis(1:dim)
1089 integer,
intent(in) :: nshifts
1090 real(real64),
intent(in) :: shift(:, :)
1091 real(real64),
intent(out) :: kpoints(:, :)
1092 integer,
optional,
intent(out) :: lk123(:, :)
1095 real(real64) :: dx(dim), maxcoord
1096 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1097 integer,
allocatable :: lk123_(:, :), idx(:)
1098 real(real64),
allocatable :: nrm(:), shell(:), coords(:, :)
1102 dx = m_one/(m_two*naxis)
1104 npoints = product(naxis)
1106 safe_allocate(idx(1:npoints*nshifts))
1107 if (
present(lk123))
then
1108 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1112 do ii = 0, npoints - 1
1113 ik = npoints*is - ii
1118 divisor = divisor / naxis(idir)
1119 ix(idir) = jj / divisor + 1
1120 jj = mod(jj, divisor)
1122 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1126 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64)
then
1127 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1131 if (
present(lk123))
then
1140 safe_allocate(nrm(1:npoints*nshifts))
1141 safe_allocate(shell(1:npoints*nshifts))
1142 safe_allocate(coords(1:dim, 1:npoints*nshifts))
1144 do ik = 1, npoints*nshifts
1145 shell(ik) = sum((kpoints(:, ik)/dx)**2)
1147 coords(idir, ik) = kpoints(idir, ik)
1148 if (coords(idir, ik) < -1e-14_real64) coords(idir, ik) = coords(idir, ik) + m_one
1149 coords(idir, ik) = coords(idir, ik)/(dx(idir)*m_two)
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
1164 call robust_sort_by_abs(nrm, kpoints, idx)
1165 do ik = 1, npoints*nshifts
1166 kpoints(:,ik) = coords(:,idx(ik))
1168 if (
present(lk123))
then
1169 do ik = 1, npoints*nshifts
1170 lk123(ik,:) = lk123_(idx(ik),:)
1172 safe_deallocate_a(lk123_)
1174 safe_deallocate_a(idx)
1176 safe_deallocate_a(nrm)
1177 safe_deallocate_a(shell)
1178 safe_deallocate_a(coords)
1185 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1186 integer,
intent(in) :: dim
1187 type(lattice_vectors_t),
intent(in) :: latt
1188 integer,
intent(in) :: nkpoints
1189 integer,
intent(in) :: nsegments
1190 integer,
intent(in) :: resolution(:)
1191 real(real64),
intent(in) :: highsympoints(:,:)
1192 real(real64),
intent(out) :: kpoints(1:dim, 1:nkpoints)
1193 real(real64),
intent(out) :: coord(1:nkpoints)
1195 integer :: is, ik, kpt_ind
1196 real(real64) :: length, total_length, accumulated_length
1197 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1201 total_length = m_zero
1202 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1204 do is = 1, nsegments
1211 if (resolution(is) > 0) total_length = total_length + length
1214 accumulated_length = m_zero
1217 do is = 1, nsegments
1226 do ik = 1, resolution(is)
1227 kpt_ind = kpt_ind +1
1228 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1229 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1231 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1234 kpt_ind = kpt_ind +1
1236 coord(kpt_ind) = accumulated_length
1237 kpoints(:, kpt_ind) = kpt1
1240 coord = coord/total_length
1247 subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, equiv, symm_ops, num_symm_ops)
1248 type(symmetries_t),
intent(in) :: symm
1249 logical,
intent(in) :: time_reversal
1250 integer,
intent(inout) :: nkpoints
1251 integer,
intent(in) :: dim
1252 real(real64),
intent(inout) :: kpoints(1:dim,1:nkpoints)
1253 real(real64),
intent(out) :: weights(1:nkpoints)
1254 integer,
intent(out) :: equiv(1:nkpoints)
1255 integer,
intent(out) :: symm_ops(:, :)
1256 integer,
intent(out) :: num_symm_ops(:)
1259 real(real64),
allocatable :: reduced(:, :)
1261 integer ik, iop, ik2
1262 real(real64) :: tran(dim), diff(dim)
1263 real(real64),
allocatable :: kweight(:)
1265 real(real64) :: prec
1272 prec = min(symprec, m_one/(nkpoints*100))
1279 safe_allocate(kweight(1:nkpoints))
1280 safe_allocate(reduced(1:dim, 1:nkpoints))
1282 kweight = m_one / nkpoints
1288 symm_ops(:, 1) = symmetries_identity_index(symm)
1291 if (kweight(ik) < prec) cycle
1295 nreduced = nreduced + 1
1296 reduced(:, nreduced) = kpoints(:, ik)
1297 equiv(ik) = nreduced
1300 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1302 if (ik == nkpoints) cycle
1305 do iop = 1, symmetries_number(symm)
1306 if (iop == symmetries_identity_index(symm) .and. &
1307 .not. time_reversal) cycle
1309 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1311 tran = tran - anint(tran + m_half*prec)
1314 do ik2 = ik + 1, nkpoints
1315 if (kweight(ik2) < prec) cycle
1317 if (.not. iop == symmetries_identity_index(symm))
then
1318 diff = tran - kpoints(:, ik2)
1319 diff = diff - anint(diff)
1322 if (sum(abs(diff)) < prec)
then
1323 kweight(ik) = kweight(ik) + kweight(ik2)
1324 kweight(ik2) = m_zero
1325 equiv(ik2) = nreduced
1326 weights(nreduced) = kweight(ik)
1327 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1328 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1333 if (time_reversal)
then
1334 diff = tran + kpoints(:, ik2)
1335 diff = diff - anint(diff)
1338 if (sum(abs(diff)) < prec)
then
1339 kweight(ik) = kweight(ik) + kweight(ik2)
1340 kweight(ik2) = m_zero
1341 equiv(ik2) = nreduced
1342 weights(nreduced) = kweight(ik)
1343 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1345 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1352 assert(sum(weights(1:nreduced)) - m_one < prec)
1353 assert(all(1 <= equiv(:)) .and. all(equiv(:) <= nreduced))
1357 kpoints(:, ik) = reduced(:, ik)
1360 safe_deallocate_a(kweight)
1361 safe_deallocate_a(reduced)
1370 type(lattice_vectors_t),
intent(in) :: latt
1372 integer :: ig1, ig2, ik
1373 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1374 real(real64) :: vec(grid%dim), kpt(grid%dim)
1375 real(real64) :: d, dmin
1380 do ig1 = 1, grid%dim
1381 do ig2 = 1, 3**grid%dim
1382 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1386 do ig1 = 1, 3**grid%dim
1390 do ik = 1, grid%npoints
1393 do ig1 = 1, 3**grid%dim
1394 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1395 d = real(sum(vec**2), real32)
1402 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1413 integer,
optional,
intent(in) :: iunit
1414 type(namespace_t),
optional,
intent(in) :: namespace
1415 logical,
optional,
intent(in) :: absolute_coordinates
1418 character(len=100) :: str_tmp
1423 call messages_print_with_emphasis(
'Brillouin zone sampling', iunit, namespace)
1427 call messages_write(
'Dimensions of the k-point grid =')
1428 do idir = 1, this%full%dim
1429 call messages_write(this%nik_axis(idir), fmt =
'(i3,1x)')
1431 call messages_new_line()
1433 if (.not. all(this%downsampling(1:this%full%dim) == 1))
then
1434 call messages_write(
'Dimensions of the q-point grid =')
1435 do idir = 1, this%full%dim
1436 call messages_write(this%niq_axis(idir), fmt =
'(i3,1x)')
1438 call messages_new_line()
1441 call messages_write(
'Total number of k-points =')
1442 call messages_write(this%full%npoints)
1443 call messages_new_line()
1445 call messages_write(
'Number of symmetry-reduced k-points =')
1446 call messages_write(this%reduced%npoints)
1448 call messages_info(iunit=iunit, namespace=namespace)
1452 call messages_write(
'Total number of k-points =')
1453 call messages_write(this%full%npoints)
1454 call messages_new_line()
1455 call messages_info(iunit=iunit, namespace=namespace)
1459 call messages_new_line()
1460 call messages_write(
'List of k-points:')
1461 call messages_info(iunit=iunit, namespace=namespace)
1463 write(message(1),
'(6x,a)')
'ik'
1464 do idir = 1, this%full%dim
1465 index = index2axis(idir)
1466 write(str_tmp,
'(9x,2a)')
'k_', index
1467 message(1) = trim(message(1)) // trim(str_tmp)
1469 write(str_tmp,
'(6x,a)')
'Weight'
1470 message(1) = trim(message(1)) // trim(str_tmp)
1471 message(2) =
'---------------------------------------------------------'
1472 call messages_info(2, iunit)
1475 write(message(1),
'(i8,1x)') ik
1476 do idir = 1, this%full%dim
1477 if (optional_default(absolute_coordinates, .false.))
then
1478 write(str_tmp,
'(f12.4)') this%reduced%point(idir, ik)
1480 write(str_tmp,
'(f12.4)') this%reduced%red_point(idir, ik)
1482 message(1) = trim(message(1)) // trim(str_tmp)
1485 message(1) = trim(message(1)) // trim(str_tmp)
1486 call messages_info(1, iunit, namespace=namespace)
1489 call messages_info(iunit=iunit, namespace=namespace)
1491 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1500 integer,
intent(in) :: ik
1508 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1510 integer,
intent(in) :: ik
1512 if (this%use_symmetries)
then
1513 num = this%num_symmetry_ops(ik)
1521 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1523 integer,
intent(in) :: ik
1524 integer,
intent(in) :: index
1526 if (this%use_symmetries)
then
1527 iop = this%symmetry_ops(ik, index)
1535 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1537 integer,
intent(in) :: ik
1538 integer,
intent(in) :: index
1543 if (this%use_symmetries)
then
1544 do iop = 1, this%num_symmetry_ops(ik)
1545 if (this%symmetry_ops(ik, iop) == index)
then
1561 integer :: denom, nik, nik_skip
1565 nik = this%full%npoints
1566 nik_skip = this%nik_skip
1573 do denom = 1, 100000
1574 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1575 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon))
then
1586 logical pure function kpoints_have_zero_weight_path(this) result(have_zerow)
1589 if (this%nik_skip > 0)
then
1592 have_zerow = .false.
1607 integer,
intent(in) :: ind
1609 coord = this%coord_along_path(ind)
1617 type(symmetries_t),
intent(in) :: symm
1618 integer,
intent(in) :: dim
1619 logical,
intent(in) :: time_reversal
1620 type(namespace_t),
intent(in) :: namespace
1622 integer,
allocatable :: kmap(:)
1623 real(real64) :: kpt(dim), diff(dim)
1624 integer :: nk, ik, ik2, iop
1625 type(distributed_t) :: kpt_dist
1632 call distributed_nullify(kpt_dist, nk)
1634 if (mpi_world%comm /= mpi_comm_undefined)
then
1635 call distributed_init(kpt_dist, nk, mpi_comm_world,
"kpt_check")
1640 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1642 do iop = 1, symmetries_number(symm)
1643 if (iop == symmetries_identity_index(symm) .and. &
1644 .not. time_reversal) cycle
1646 do ik = kpt_dist%start, kpt_dist%end
1650 do ik = kpt_dist%start, kpt_dist%end
1652 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1654 kpt = kpt - anint(kpt + m_half*symprec)
1659 if (iop /= symmetries_identity_index(symm))
then
1660 diff = kpt - grid%red_point(:, ik2)
1661 diff = diff - anint(diff)
1663 if (sum(abs(diff)) < symprec)
then
1669 if (time_reversal)
then
1670 diff = kpt + grid%red_point(:, ik2)
1671 diff = diff - anint(diff)
1673 if (sum(abs(diff)) < symprec)
then
1681 if (kmap(ik) == ik)
then
1682 write(message(1),
'(a,i5,a2,3(f7.3,a2),a)')
"The reduced k-point ", ik,
" (", &
1683 grid%red_point(1, ik),
", ", grid%red_point(2, ik),
", ", grid%red_point(3, ik), &
1684 ") ",
"has no symmetric in the k-point grid for the following symmetry"
1685 write(message(2),
'(i5,1x,a,2x,3(3i4,2x))') iop,
':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1686 message(3) =
"Change your k-point grid or use KPointsUseSymmetries=no."
1687 call messages_fatal(3, namespace=namespace)
1692 safe_deallocate_a(kmap)
1694 call distributed_end(kpt_dist)
1702 integer,
intent(in) :: ik
1703 integer,
intent(in) :: iq
1705 integer :: dim, idim
1706 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1711 dim = kpt%reduced%dim
1714 if (all(kpt%downsampling == 1))
then
1721 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1724 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1725 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1726 if (abs(red(idim) - anint(red(idim))) > m_epsilon)
then
1727 compatible = .false.
1741 if (
allocated(this%coord_along_path))
then
1742 npath =
SIZE(this%coord_along_path)
1761 type(lattice_vectors_t),
intent(in) :: new_latt
1767 this%latt = new_latt
1769 do ik = 1, this%reduced%npoints
1770 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1773 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.