25 use,
intrinsic :: iso_fortran_env
76 real(real64),
allocatable :: point(:, :)
77 real(real64),
allocatable :: point1BZ(:, :)
78 real(real64),
allocatable :: red_point(:, :)
79 real(real64),
allocatable :: weight(:)
80 type(simplex_t),
pointer :: simplex => null()
81 integer :: nshifts = 1
82 real(real64),
allocatable :: shifts(:, :)
83 integer :: npoints = 0
90 type(lattice_vectors_t) :: latt
92 type(kpoints_grid_t) :: full
93 type(kpoints_grid_t) :: reduced
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 :: lk123(:, :)
107 integer,
allocatable,
private :: symmetry_ops(:, :)
108 integer,
allocatable,
private :: num_symmetry_ops(:)
109 integer,
allocatable,
private :: map_full_to_reduced(:)
110 integer,
allocatable,
private :: map_full_to_symidx(:)
113 real(real64),
allocatable,
private :: coord_along_path(:)
115 integer,
allocatable :: downsampling(:)
117 type(symmetries_t),
pointer :: symm => null()
131 integer,
public,
parameter :: &
141 integer,
intent(in) :: dim
142 type(kpoints_grid_t),
intent(out) :: this
143 integer,
intent(in) :: npoints
144 integer,
intent(in) :: nshifts
149 this%npoints = npoints
150 this%nshifts = nshifts
151 safe_allocate(this%red_point(1:dim, 1:npoints))
152 safe_allocate(this%point(1:dim, 1:npoints))
153 safe_allocate(this%point1bz(1:dim,1:npoints))
154 safe_allocate(this%weight(1:npoints))
155 safe_allocate(this%shifts(1:dim,1:nshifts))
162 type(kpoints_grid_t),
intent(inout) :: this
166 safe_deallocate_a(this%red_point)
167 safe_deallocate_a(this%point)
168 safe_deallocate_a(this%point1BZ)
169 safe_deallocate_a(this%weight)
170 safe_deallocate_a(this%shifts)
171 safe_deallocate_p(this%simplex)
185 aa%weight(1:bb%npoints) = bb%weight(1:bb%npoints)
186 aa%point(1:bb%dim, 1:bb%npoints) = bb%point(1:bb%dim, 1:bb%npoints)
187 aa%point1BZ(1:bb%dim, 1:bb%npoints) = bb%point1BZ(1:bb%dim, 1:bb%npoints)
188 aa%red_point(1:bb%dim, 1:bb%npoints) = bb%red_point(1:bb%dim, 1:bb%npoints)
189 aa%shifts(1:bb%dim, 1:bb%nshifts) = bb%shifts(1:bb%dim, 1:bb%nshifts)
203 if (.not.
allocated(that%point))
then
208 if (.not.
allocated(this%point))
then
225 this%red_point(1:old_grid%dim, 1:old_grid%npoints)= old_grid%red_point(1:old_grid%dim, 1:old_grid%npoints)
226 this%point(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point(1:old_grid%dim, 1:old_grid%npoints)
227 this%point1BZ(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point1BZ(1:old_grid%dim, 1:old_grid%npoints)
228 this%weight(1:old_grid%npoints) = old_grid%weight(1:old_grid%npoints)
229 this%shifts(1:old_grid%dim, 1:old_grid%nshifts) = old_grid%shifts(1:old_grid%dim, 1:old_grid%nshifts)
232 this%red_point(1:old_grid%dim, old_grid%npoints+1:this%npoints)= that%red_point(1:that%dim, 1:that%npoints)
233 this%point(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point(1:that%dim, 1:that%npoints)
234 this%point1BZ(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point1BZ(1:that%dim, 1:that%npoints)
235 this%weight(old_grid%npoints+1:this%npoints) = that%weight(1:that%npoints)
247 logical,
intent(in) :: use_symmetries
248 logical,
intent(in) :: only_gamma
257 method = kpoints_gamma
270 if (use_symmetries)
then
271 write(
message(1),
'(a)')
"User-defined k-points are not compatible with KPointsUseSymmetries=yes."
279 if (use_symmetries)
then
280 write(
message(1),
'(a)')
"KPointsPath is not compatible with KPointsUseSymmetries=yes."
285 if (method == 0)
then
286 write(
message(1),
'(a)')
"Unable to determine the method for defining k-points."
287 write(
message(2),
'(a)')
"Octopus will continue assuming a Monkhorst Pack grid."
300 integer,
intent(in) :: dim
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
316 safe_deallocate_a(this%map_full_to_reduced)
317 safe_deallocate_a(this%map_full_to_symidx)
323 subroutine kpoints_init(this, namespace, symm, dim, periodic_dim, latt)
327 integer,
intent(in) :: dim
328 integer,
intent(in) :: periodic_dim
331 logical :: only_gamma, default_timereversal
352 call parse_variable(namespace,
'KPointsUseSymmetries', .false., this%use_symmetries)
372 call parse_variable(namespace,
'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
374 only_gamma = (periodic_dim == 0)
406 integer,
intent(in) :: dim
407 logical,
intent(in) :: gamma_only
409 logical :: gamma_only_
410 integer :: ii, ik, is, ncols, nshifts
412 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
413 real(real64),
allocatable :: shifts(:, :)
461 gamma_only_ = gamma_only
462 if (.not. gamma_only_)
then
463 gamma_only_ = (
parse_block(namespace,
'KPointsGrid', blk) /= 0)
468 if (.not. gamma_only_)
then
473 safe_allocate(shifts(1:dim,1:nshifts))
476 if (.not. gamma_only_)
then
478 if (ncols /= dim)
then
479 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid first row has ', ncols,
' columns but should have ', dim
480 if (ncols < dim)
then
483 write(
message(2),
'(a)')
'Continuing, but ignoring the additional values.'
491 if (any(this%nik_axis < 1))
then
492 message(1) =
'Input: KPointsGrid is not valid.'
498 if (ncols /= dim)
then
499 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid shift has ', ncols,
' columns but must have ', dim
510 if (mod(this%nik_axis(ii), 2) /= 0)
then
540 this%niq_axis(:) = this%nik_axis(:)
541 this%downsampling(:) = 1
543 if (
parse_block(namespace,
'QPointsGrid', blk) == 0)
then
545 if (ncols /= dim)
then
546 write(
message(1),
'(a,i3,a,i3)')
'QPointsGrid first row has ', ncols,
' columns but must have ', dim
553 if (any(this%nik_axis/this%niq_axis /= nint(this%nik_axis/real(this%niq_axis))))
then
554 message(1) =
'Input: QPointsGrid is not compatible with the KPointsGrid.'
558 this%downsampling = this%nik_axis/this%niq_axis
560 if (any(this%downsampling /= 1) .and. this%use_symmetries)
then
571 this%full%shifts(:, :) = shifts(:, :)
572 safe_deallocate_a(shifts)
576 safe_allocate(this%lk123(1:this%full%npoints, 1:dim))
577 call kpoints_grid_generate(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
580 do ik = 1, this%full%npoints
584 this%full%weight =
m_one / this%full%npoints
586 if (this%use_symmetries)
then
587 message(1) =
"Checking if the generated full k-point grid is symmetric"
594 if (this%use_symmetries)
then
595 safe_allocate(num_symm_ops(1:this%full%npoints))
597 if (this%use_time_reversal)
then
603 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
604 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
606 this%reduced%npoints, dim, this%reduced%red_point, this%reduced%weight, this%map_full_to_reduced, &
607 this%map_full_to_symidx, symm_ops, num_symm_ops)
609 assert(maxval(num_symm_ops) >= 1)
610 if (this%use_time_reversal)
then
617 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
619 do ik = 1, this%reduced%npoints
620 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
623 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)))
624 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
626 this%num_symmetry_ops(1:this%reduced%npoints) = num_symm_ops(1:this%reduced%npoints)
627 this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)) = &
628 symm_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops))
630 safe_deallocate_a(num_symm_ops)
631 safe_deallocate_a(symm_ops)
633 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
634 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1))
635 this%num_symmetry_ops(1:this%reduced%npoints) = 1
636 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
637 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
638 do ik = 1, this%full%npoints
639 this%map_full_to_reduced(ik) = ik
641 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
642 this%map_full_to_symidx(:) = 1
645 do ik = 1, this%reduced%npoints
646 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
653 integer(int64) :: dos_method, smearing_function
654 logical :: use_simplex, use_simplex_opt
656 call parse_variable(namespace,
'DOSMethod', option__dosmethod__smear, dos_method)
657 call parse_variable(namespace,
'SmearingFunction', option__smearingfunction__semiconducting, smearing_function)
659 use_simplex = dos_method == option__dosmethod__tetrahedra .or. &
660 smearing_function == option__smearingfunction__tetrahedra
661 use_simplex_opt = dos_method == option__dosmethod__tetrahedra_opt .or. &
662 smearing_function == option__smearingfunction__tetrahedra_opt
664 if (use_simplex .and. use_simplex_opt)
then
665 call messages_not_implemented(
"DOSMethod and SmearingFunction with different tetrahedron methods", namespace=namespace)
668 if (use_simplex .or. use_simplex_opt)
then
669 safe_deallocate_p(this%full%simplex)
670 safe_deallocate_p(this%reduced%simplex)
673 if (use_simplex)
then
674 this%full%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
676 this%reduced%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
677 equiv = this%map_full_to_reduced, opt = .false.)
678 elseif (use_simplex_opt)
then
679 this%full%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
681 this%reduced%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
682 equiv = this%map_full_to_reduced, opt = .
true.)
693 type(namespace_t),
intent(in) :: namespace
694 integer,
intent(in) :: dim
697 integer :: nshifts, nkpoints, nhighsympoints, nsegments
698 integer :: icol, ik, idir, ncols, npoints
699 integer,
allocatable :: resolution(:)
700 real(real64),
allocatable :: highsympoints(:, :)
702 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
730 if (parse_block(namespace,
'KPointsPath', blk) /= 0)
then
731 write(message(1),
'(a)')
'Internal error while reading KPointsPath.'
732 call messages_fatal(1, namespace=namespace)
736 nsegments = parse_block_cols(blk, 0)
737 nhighsympoints = parse_block_n(blk) - 1
738 if (nhighsympoints /= nsegments + 1)
then
739 write(message(1),
'(a,i3,a,i3)')
'The first row of KPointsPath is not compatible with the number of specified k-points.'
740 call messages_fatal(1, namespace=namespace)
743 safe_allocate(resolution(1:nsegments))
744 do icol = 1, nsegments
745 call parse_block_integer(blk, 0, icol-1, resolution(icol))
748 nkpoints = sum(resolution) + 1
750 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
751 do ik = 1, nhighsympoints
752 ncols = parse_block_cols(blk, ik)
753 if (ncols /= dim)
then
754 write(message(1),
'(a,i8,a,i3,a,i3)')
'KPointsPath row ', ik,
' has ', ncols,
' columns but must have ', dim
755 call messages_fatal(1, namespace=namespace)
759 call parse_block_float(blk, ik, idir-1, highsympoints(idir, ik))
763 call parse_block_end(blk)
770 safe_allocate(this%coord_along_path(1:nkpoints))
772 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
773 this%coord_along_path)
775 safe_deallocate_a(resolution)
776 safe_deallocate_a(highsympoints)
781 path_kpoints_grid%weight = m_one/path_kpoints_grid%npoints
783 path_kpoints_grid%weight = m_zero
784 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
788 do ik = 1, path_kpoints_grid%npoints
789 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
796 if (
allocated(this%symmetry_ops))
then
797 npoints = this%reduced%npoints
798 safe_allocate(num_symm_ops(1:npoints))
799 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
801 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
802 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
803 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
809 if (
allocated(this%symmetry_ops))
then
810 safe_deallocate_a(this%num_symmetry_ops)
811 safe_deallocate_a(this%symmetry_ops)
812 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
813 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
815 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
816 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
817 symm_ops(1:npoints, 1:maxval(num_symm_ops))
818 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
819 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
821 safe_deallocate_a(num_symm_ops)
822 safe_deallocate_a(symm_ops)
823 else if(this%use_symmetries)
then
824 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
825 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
827 this%num_symmetry_ops(1:this%reduced%npoints) = 1
828 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
840 type(namespace_t),
intent(in) :: namespace
841 integer,
intent(in) :: dim
846 real(real64) :: weight_sum
884 if (parse_block(namespace,
'KPoints', blk) /= 0)
then
885 if (parse_block(namespace,
'KPointsReduced', blk) == 0)
then
889 write(message(1),
'(a)')
'Internal error loading user-defined k-point list.'
890 call messages_fatal(1, namespace=namespace)
896 user_kpoints_grid%red_point = m_zero
897 user_kpoints_grid%point = m_zero
898 user_kpoints_grid%weight = m_zero
899 user_kpoints_grid%shifts = m_zero
902 do ik = 1, user_kpoints_grid%npoints
903 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
905 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%red_point(idir, ik))
908 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
911 do ik = 1, user_kpoints_grid%npoints
912 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
914 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%point(idir, ik), unit_one/units_inp%length)
917 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
920 call parse_block_end(blk)
923 if (any(user_kpoints_grid%weight < m_epsilon))
then
924 call messages_experimental(
'K-points with zero weight')
925 message(1) =
"Found k-points with zero weight. They are excluded from density calculation"
926 call messages_warning(1, namespace=namespace)
931 do ik=1,user_kpoints_grid%npoints
932 if (user_kpoints_grid%weight(ik) < m_epsilon)
then
934 if (ik < user_kpoints_grid%npoints)
then
935 if (user_kpoints_grid%weight(ik+1) > m_epsilon)
then
936 message(1) =
"K-points with zero weight must follow all regular k-points in a block"
937 call messages_fatal(1, namespace=namespace)
940 this%nik_skip = this%nik_skip + 1
941 user_kpoints_grid%weight(ik) = m_zero
946 weight_sum = sum(user_kpoints_grid%weight)
947 if (weight_sum < m_epsilon)
then
948 message(1) =
"k-point weights must sum to a positive number."
949 call messages_fatal(1, namespace=namespace)
951 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
961 write(message(1),
'(a,i4,a)')
'Input: ', user_kpoints_grid%npoints,
' k-points were read from the input file'
962 call messages_info(1, namespace=namespace)
978 safe_deallocate_a(this%nik_axis)
979 safe_deallocate_a(this%niq_axis)
980 safe_deallocate_a(this%lk123)
981 safe_deallocate_a(this%downsampling)
982 safe_deallocate_a(this%symmetry_ops)
983 safe_deallocate_a(this%num_symmetry_ops)
984 safe_deallocate_a(this%map_full_to_reduced)
985 safe_deallocate_a(this%map_full_to_symidx)
986 safe_deallocate_a(this%coord_along_path)
994 type(namespace_t),
intent(in) :: namespace
996 integer :: idir, is, ik, dim
997 character(len=100) :: str_tmp
1001 dim = this%reduced%dim
1004 write(message(1),
'(a)')
' '
1005 write(message(2),
'(1x,i5,a)') this%reduced%npoints,
' k-points generated from parameters :'
1006 write(message(3),
'(1x,a)')
'---------------------------------------------------'
1007 write(message(4),
'(4x,a)')
'n ='
1009 write(str_tmp,
'(i5)') this%nik_axis(idir)
1010 message(4) = trim(message(4)) // trim(str_tmp)
1012 call messages_info(4, namespace=namespace)
1014 do is = 1, this%reduced%nshifts
1015 write(message(1),
'(a)')
' '
1016 write(message(2),
'(4x,a,i1,a)')
's', is,
' ='
1018 write(str_tmp,
'(f6.2)') this%reduced%shifts(idir,is)
1019 message(2) = trim(message(2)) // trim(str_tmp)
1021 call messages_info(2, namespace=namespace)
1025 write(message(1),
'(a)')
' '
1026 write(message(2),
'(a)')
' index | weight | coordinates |'
1027 call messages_info(2, namespace=namespace)
1029 do ik = 1, this%reduced%npoints
1030 write(str_tmp,
'(i8,a,f12.6,a)') ik,
" | ", this%reduced%weight(ik),
" |"
1031 message(1) = str_tmp
1033 write(str_tmp,
'(f12.6)') this%reduced%red_point(idir, ik)
1034 message(1) = trim(message(1)) // trim(str_tmp)
1036 write(str_tmp,
'(a)')
" |"
1037 message(1) = trim(message(1)) // trim(str_tmp)
1038 call messages_info(1, namespace=namespace)
1041 write(message(1),
'(a)')
' '
1042 call messages_info(1, namespace=namespace)
1050 type(lattice_vectors_t),
intent(in) :: latt
1051 real(real64),
intent(in) :: kin(:)
1052 real(real64),
intent(out) :: kout(:)
1056 kout = matmul(latt%klattice, kin)
1063 type(lattice_vectors_t),
intent(in) :: latt
1064 real(real64),
intent(in) :: kin(:)
1065 real(real64),
intent(out) :: kout(:)
1069 kout = matmul(kin, latt%rlattice) / (m_two*m_pi)
1084 kout%method = kin%method
1089 kout%use_symmetries = kin%use_symmetries
1090 kout%use_time_reversal = kin%use_time_reversal
1092 safe_allocate(kout%nik_axis(1:kin%full%dim))
1093 safe_allocate(kout%niq_axis(1:kin%full%dim))
1094 safe_allocate(kout%downsampling(1:kin%full%dim))
1095 kout%nik_axis(:) = kin%nik_axis(:)
1096 kout%niq_axis(:) = kin%niq_axis(:)
1097 kout%downsampling(:) = kin%downsampling(:)
1099 if (
allocated(kin%lk123))
then
1100 safe_allocate(kout%lk123(1:kin%full%npoints, 1:kin%full%dim))
1101 kout%lk123(:, :) = kin%lk123(:, :)
1104 if (
allocated(kin%coord_along_path))
then
1105 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1106 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1109 if (
allocated(kin%symmetry_ops))
then
1110 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1111 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1112 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1113 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1114 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1116 if (
allocated(kin%map_full_to_symidx))
then
1117 safe_allocate(kout%map_full_to_symidx(1:kin%full%npoints))
1118 kout%map_full_to_symidx(1:kin%full%npoints) = kin%map_full_to_symidx(1:kin%full%npoints)
1120 if (
allocated(kin%map_full_to_reduced))
then
1121 safe_allocate(kout%map_full_to_reduced(1:kin%full%npoints))
1122 kout%map_full_to_reduced(1:kin%full%npoints) = kin%map_full_to_reduced(1:kin%full%npoints)
1130 integer pure function kpoints_number(this) result(number)
1133 number = this%reduced%npoints
1141 integer,
intent(in) :: ik
1142 logical,
optional,
intent(in) :: absolute_coordinates
1143 real(real64) :: point(1:this%full%dim)
1145 if (optional_default(absolute_coordinates, .
true.))
then
1146 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1148 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1157 integer,
intent(in) :: ik
1159 weight = this%reduced%weight(ik)
1175 integer,
intent(in) :: ik
1177 assert(
allocated(this%map_full_to_reduced))
1178 equiv = this%map_full_to_reduced(ik)
1192 integer,
intent(in) :: dim
1193 integer,
intent(in) :: naxis(1:dim)
1194 integer,
intent(in) :: nshifts
1195 real(real64),
intent(in) :: shift(:, :)
1196 real(real64),
intent(out) :: kpoints(:, :)
1197 integer,
optional,
intent(out) :: lk123(:, :)
1200 real(real64) :: dx(dim)
1201 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1202 integer,
allocatable :: lk123_(:, :), idx(:)
1206 dx = m_one/(m_two*naxis)
1208 npoints = product(naxis)
1210 safe_allocate(idx(1:npoints*nshifts))
1211 if (
present(lk123))
then
1212 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1216 do ii = 0, npoints - 1
1217 ik = npoints*is - ii
1222 divisor = divisor / naxis(idir)
1223 ix(idir) = jj / divisor + 1
1224 jj = mod(jj, divisor)
1226 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1230 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64)
then
1231 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1235 if (
present(lk123))
then
1244 if (
present(lk123))
then
1245 do ik = 1, npoints*nshifts
1246 lk123(ik,:) = lk123_(idx(ik),:)
1248 safe_deallocate_a(lk123_)
1251 safe_deallocate_a(idx)
1266 integer,
intent(in ) :: nik_axis(:)
1267 real(real64),
intent(inout) :: kpoints(:, :)
1270 integer,
optional,
intent(in) :: nshifts
1271 integer,
optional,
intent(out) :: indices(:)
1274 integer :: ndim, nk, ik, nshifts_
1275 real(real64) :: dk(size(kpoints, 1))
1276 integer,
allocatable :: idx(:)
1277 real(real64),
allocatable :: shell(:), kpoints_unsorted(:, :)
1281 ndim =
size(kpoints, 1)
1282 nshifts_ = optional_default(nshifts, 1)
1283 nk = product(nik_axis) * nshifts_
1288 dk = m_one / (m_two * nik_axis)
1290 safe_allocate(shell(1:nk))
1291 safe_allocate(idx(1:nk))
1292 safe_allocate_source(kpoints_unsorted(1:ndim, 1:nk), kpoints)
1296 shell(ik) = sum((kpoints_unsorted(:, ik) / dk)**2)
1299 call robust_sort_by_abs(shell, kpoints_unsorted, idx)
1300 safe_deallocate_a(shell)
1303 kpoints(:, ik) = kpoints_unsorted(:, idx(ik))
1306 if (
present(indices)) indices = idx
1308 safe_deallocate_a(idx)
1309 safe_deallocate_a(kpoints_unsorted)
1317 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1318 integer,
intent(in) :: dim
1319 type(lattice_vectors_t),
intent(in) :: latt
1320 integer,
intent(in) :: nkpoints
1321 integer,
intent(in) :: nsegments
1322 integer,
intent(in) :: resolution(:)
1323 real(real64),
intent(in) :: highsympoints(:,:)
1324 real(real64),
intent(out) :: kpoints(1:dim, 1:nkpoints)
1325 real(real64),
intent(out) :: coord(1:nkpoints)
1327 integer :: is, ik, kpt_ind
1328 real(real64) :: length, total_length, accumulated_length
1329 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1333 total_length = m_zero
1334 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1336 do is = 1, nsegments
1343 if (resolution(is) > 0) total_length = total_length + length
1346 accumulated_length = m_zero
1349 do is = 1, nsegments
1356 if (length > m_epsilon) vec = vec/length
1358 do ik = 1, resolution(is)
1359 kpt_ind = kpt_ind +1
1360 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1361 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1363 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1366 kpt_ind = kpt_ind +1
1368 coord(kpt_ind) = accumulated_length
1369 kpoints(:, kpt_ind) = kpt1
1372 coord = coord/total_length
1380 map_full_to_reduced, map_full_to_symidx, symm_ops, num_symm_ops)
1381 type(symmetries_t),
intent(in) :: symm
1382 logical,
intent(in) :: time_reversal
1383 integer,
intent(inout) :: nkpoints
1384 integer,
intent(in) :: dim
1385 real(real64),
intent(inout) :: kpoints(1:dim,1:nkpoints)
1386 real(real64),
intent(out) :: weights(1:nkpoints)
1387 integer,
intent(out) :: map_full_to_reduced(1:nkpoints)
1388 integer,
intent(out) :: map_full_to_symidx(1:nkpoints)
1389 integer,
intent(out) :: symm_ops(:, :)
1390 integer,
intent(out) :: num_symm_ops(:)
1393 real(real64),
allocatable :: reduced(:, :)
1395 integer ik, iop, ik2
1396 real(real64) :: tran(dim), diff(dim)
1397 real(real64),
allocatable :: kweight(:)
1399 real(real64) :: prec
1406 prec = min(symprec, m_one/(nkpoints*100))
1413 safe_allocate(kweight(1:nkpoints))
1414 safe_allocate(reduced(1:dim, 1:nkpoints))
1416 kweight = m_one / nkpoints
1419 map_full_to_reduced(:) = -1
1420 map_full_to_symidx(:) = -1
1423 symm_ops(:, 1) = symmetries_identity_index(symm)
1426 if (kweight(ik) < prec) cycle
1430 nreduced = nreduced + 1
1431 reduced(:, nreduced) = kpoints(:, ik)
1432 map_full_to_reduced(ik) = nreduced
1433 map_full_to_symidx(ik) = 1
1436 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1438 if (ik == nkpoints) cycle
1441 do iop = 1, symmetries_number(symm)
1442 if (iop == symmetries_identity_index(symm) .and. &
1443 .not. time_reversal) cycle
1445 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1447 tran = tran - anint(tran + m_half*prec)
1450 do ik2 = ik + 1, nkpoints
1451 if (kweight(ik2) < prec) cycle
1453 if (.not. iop == symmetries_identity_index(symm))
then
1454 diff = tran - kpoints(:, ik2)
1455 diff = diff - anint(diff)
1458 if (sum(abs(diff)) < prec)
then
1459 kweight(ik) = kweight(ik) + kweight(ik2)
1460 kweight(ik2) = m_zero
1461 map_full_to_reduced(ik2) = nreduced
1462 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1463 weights(nreduced) = kweight(ik)
1464 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1465 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1470 if (time_reversal)
then
1471 diff = tran + kpoints(:, ik2)
1472 diff = diff - anint(diff)
1475 if (sum(abs(diff)) < prec)
then
1476 kweight(ik) = kweight(ik) + kweight(ik2)
1477 kweight(ik2) = m_zero
1478 map_full_to_reduced(ik2) = nreduced
1479 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1480 weights(nreduced) = kweight(ik)
1481 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1483 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1490 assert(sum(weights(1:nreduced)) - m_one < prec)
1491 assert(all(1 <= map_full_to_reduced(:)) .and. all(map_full_to_reduced(:) <= nreduced))
1492 assert(all(1 <= map_full_to_symidx(:)) .and. all(map_full_to_symidx(:) <=
size(symm_ops, 2)))
1496 kpoints(:, ik) = reduced(:, ik)
1499 safe_deallocate_a(kweight)
1500 safe_deallocate_a(reduced)
1509 type(lattice_vectors_t),
intent(in) :: latt
1511 integer :: ig1, ig2, ik
1512 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1513 real(real64) :: vec(grid%dim), kpt(grid%dim)
1514 real(real64) :: d, dmin
1519 do ig1 = 1, grid%dim
1520 do ig2 = 1, 3**grid%dim
1521 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1525 do ig1 = 1, 3**grid%dim
1529 do ik = 1, grid%npoints
1532 do ig1 = 1, 3**grid%dim
1533 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1534 d = real(sum(vec**2), real32)
1541 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1552 integer,
optional,
intent(in) :: iunit
1553 type(namespace_t),
optional,
intent(in) :: namespace
1554 logical,
optional,
intent(in) :: absolute_coordinates
1557 character(len=100) :: str_tmp
1562 call messages_print_with_emphasis(
'Brillouin zone sampling', iunit, namespace)
1566 call messages_write(
'Dimensions of the k-point grid =')
1567 do idir = 1, this%full%dim
1568 call messages_write(this%nik_axis(idir), fmt =
'(i3,1x)')
1570 call messages_new_line()
1572 if (.not. all(this%downsampling(1:this%full%dim) == 1))
then
1573 call messages_write(
'Dimensions of the q-point grid =')
1574 do idir = 1, this%full%dim
1575 call messages_write(this%niq_axis(idir), fmt =
'(i3,1x)')
1577 call messages_new_line()
1580 call messages_write(
'Total number of k-points =')
1581 call messages_write(this%full%npoints)
1582 call messages_new_line()
1584 call messages_write(
'Number of symmetry-reduced k-points =')
1585 call messages_write(this%reduced%npoints)
1587 call messages_info(iunit=iunit, namespace=namespace)
1591 call messages_write(
'Total number of k-points =')
1592 call messages_write(this%full%npoints)
1593 call messages_new_line()
1594 call messages_info(iunit=iunit, namespace=namespace)
1598 call messages_new_line()
1599 call messages_write(
'List of k-points:')
1600 call messages_info(iunit=iunit, namespace=namespace)
1602 write(message(1),
'(6x,a)')
'ik'
1603 do idir = 1, this%full%dim
1604 index = index2axis(idir)
1605 write(str_tmp,
'(9x,2a)')
'k_', index
1606 message(1) = trim(message(1)) // trim(str_tmp)
1608 write(str_tmp,
'(6x,a)')
'Weight'
1609 message(1) = trim(message(1)) // trim(str_tmp)
1610 message(2) =
'---------------------------------------------------------'
1611 call messages_info(2, iunit)
1614 write(message(1),
'(i8,1x)') ik
1615 do idir = 1, this%full%dim
1616 if (optional_default(absolute_coordinates, .false.))
then
1617 write(str_tmp,
'(f12.4)') this%reduced%point(idir, ik)
1619 write(str_tmp,
'(f12.4)') this%reduced%red_point(idir, ik)
1621 message(1) = trim(message(1)) // trim(str_tmp)
1624 message(1) = trim(message(1)) // trim(str_tmp)
1625 call messages_info(1, iunit, namespace=namespace)
1628 call messages_info(iunit=iunit, namespace=namespace)
1630 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1639 integer,
intent(in) :: ik
1647 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1649 integer,
intent(in) :: ik
1651 if (this%use_symmetries)
then
1652 num = this%num_symmetry_ops(ik)
1660 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1662 integer,
intent(in) :: ik
1663 integer,
intent(in) :: index
1665 if (this%use_symmetries)
then
1666 iop = this%symmetry_ops(ik, index)
1683 integer pure function kpoints_get_full_symmetry_op_index(this, ifull) result(iiop)
1685 integer,
intent(in) :: ifull
1687 if (this%use_symmetries)
then
1688 iiop = this%map_full_to_symidx(ifull)
1696 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1698 integer,
intent(in) :: ik
1699 integer,
intent(in) :: index
1704 if (this%use_symmetries)
then
1705 do iop = 1, this%num_symmetry_ops(ik)
1706 if (this%symmetry_ops(ik, iop) == index)
then
1722 integer :: denom, nik, nik_skip
1726 nik = this%full%npoints
1727 nik_skip = this%nik_skip
1734 do denom = 1, 100000
1735 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1736 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon))
then
1750 if (this%nik_skip > 0)
then
1753 have_zerow = .false.
1768 integer,
intent(in) :: ind
1770 coord = this%coord_along_path(ind)
1778 type(symmetries_t),
intent(in) :: symm
1779 integer,
intent(in) :: dim
1780 logical,
intent(in) :: time_reversal
1781 type(namespace_t),
intent(in) :: namespace
1783 integer,
allocatable :: kmap(:)
1784 real(real64) :: kpt(dim), diff(dim)
1785 integer :: nk, ik, ik2, iop
1786 type(distributed_t) :: kpt_dist
1793 call distributed_init(kpt_dist, nk, mpi_world%comm,
"kpt_check")
1796 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1798 do iop = 1, symmetries_number(symm)
1799 if (iop == symmetries_identity_index(symm) .and. &
1800 .not. time_reversal) cycle
1802 do ik = kpt_dist%start, kpt_dist%end
1806 do ik = kpt_dist%start, kpt_dist%end
1808 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1810 kpt = kpt - anint(kpt + m_half*symprec)
1815 if (iop /= symmetries_identity_index(symm))
then
1816 diff = kpt - grid%red_point(:, ik2)
1817 diff = diff - anint(diff)
1819 if (sum(abs(diff)) < symprec)
then
1825 if (time_reversal)
then
1826 diff = kpt + grid%red_point(:, ik2)
1827 diff = diff - anint(diff)
1829 if (sum(abs(diff)) < symprec)
then
1837 if (kmap(ik) == ik)
then
1838 write(message(1),
'(a,i5,a2,3(f7.3,a2),a)')
"The reduced k-point ", ik,
" (", &
1839 grid%red_point(1, ik),
", ", grid%red_point(2, ik),
", ", grid%red_point(3, ik), &
1840 ") ",
"has no symmetric in the k-point grid for the following symmetry"
1841 write(message(2),
'(i5,1x,a,2x,3(3i4,2x))') iop,
':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1842 message(3) =
"Change your k-point grid or use KPointsUseSymmetries=no."
1843 call messages_fatal(3, namespace=namespace)
1848 safe_deallocate_a(kmap)
1850 call distributed_end(kpt_dist)
1858 integer,
intent(in) :: ik
1859 integer,
intent(in) :: iq
1861 integer :: dim, idim
1862 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1867 dim = kpt%reduced%dim
1870 if (all(kpt%downsampling == 1))
then
1877 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1880 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1881 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1882 if (abs(red(idim) - anint(red(idim))) > m_epsilon)
then
1883 compatible = .false.
1897 if (
allocated(this%coord_along_path))
then
1898 npath =
SIZE(this%coord_along_path)
1917 type(lattice_vectors_t),
intent(in) :: new_latt
1923 this%latt = new_latt
1925 do ik = 1, this%reduced%npoints
1926 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1929 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.
logical pure function, public kpoints_is_valid_symmetry(this, ik, index)
integer function, public kpoints_kweight_denominator(this)
subroutine, public kpoints_copy(kin, kout)
integer pure function, public kpoints_get_full_symmetry_op_index(this, ifull)
Return symmetry-op list index for a full-grid k-point.
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)
integer function kpoints_get_equiv(this, ik)
Map a full-grid k-point index to its reduced-grid representative.
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 kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, map_full_to_reduced, map_full_to_symidx, symm_ops, num_symm_ops)
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.