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, grp)
327 integer,
intent(in) :: dim
328 integer,
intent(in) :: periodic_dim
332 logical :: only_gamma, default_timereversal
353 call parse_variable(namespace,
'KPointsUseSymmetries', .false., this%use_symmetries)
373 call parse_variable(namespace,
'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
375 only_gamma = (periodic_dim == 0)
386 call kpoints_read_mp(this, namespace, symm, dim, grp, gamma_only=.false.)
403 subroutine kpoints_read_mp(this, namespace, symm, dim, grp, gamma_only)
407 integer,
intent(in) :: dim
409 logical,
intent(in) :: gamma_only
411 logical :: gamma_only_
412 integer :: ii, ik, is, ncols, nshifts
414 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
415 real(real64),
allocatable :: shifts(:, :)
463 gamma_only_ = gamma_only
464 if (.not. gamma_only_)
then
465 gamma_only_ = (
parse_block(namespace,
'KPointsGrid', blk) /= 0)
470 if (.not. gamma_only_)
then
475 safe_allocate(shifts(1:dim,1:nshifts))
478 if (.not. gamma_only_)
then
480 if (ncols /= dim)
then
481 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid first row has ', ncols,
' columns but should have ', dim
482 if (ncols < dim)
then
485 write(
message(2),
'(a)')
'Continuing, but ignoring the additional values.'
493 if (any(this%nik_axis < 1))
then
494 message(1) =
'Input: KPointsGrid is not valid.'
500 if (ncols /= dim)
then
501 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid shift has ', ncols,
' columns but must have ', dim
512 if (mod(this%nik_axis(ii), 2) /= 0)
then
542 this%niq_axis(:) = this%nik_axis(:)
543 this%downsampling(:) = 1
545 if (
parse_block(namespace,
'QPointsGrid', blk) == 0)
then
547 if (ncols /= dim)
then
548 write(
message(1),
'(a,i3,a,i3)')
'QPointsGrid first row has ', ncols,
' columns but must have ', dim
555 if (any(this%nik_axis/this%niq_axis /= nint(this%nik_axis/real(this%niq_axis))))
then
556 message(1) =
'Input: QPointsGrid is not compatible with the KPointsGrid.'
560 this%downsampling = this%nik_axis/this%niq_axis
562 if (any(this%downsampling /= 1) .and. this%use_symmetries)
then
573 this%full%shifts(:, :) = shifts(:, :)
574 safe_deallocate_a(shifts)
578 safe_allocate(this%lk123(1:this%full%npoints, 1:dim))
579 call kpoints_grid_generate(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
582 do ik = 1, this%full%npoints
586 this%full%weight =
m_one / this%full%npoints
588 if (this%use_symmetries)
then
589 message(1) =
"Checking if the generated full k-point grid is symmetric"
596 if (this%use_symmetries)
then
597 safe_allocate(num_symm_ops(1:this%full%npoints))
599 if (this%use_time_reversal)
then
605 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
606 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
608 this%reduced%npoints, dim, this%reduced%red_point, this%reduced%weight, this%map_full_to_reduced, &
609 this%map_full_to_symidx, symm_ops, num_symm_ops)
611 assert(maxval(num_symm_ops) >= 1)
612 if (this%use_time_reversal)
then
619 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
621 do ik = 1, this%reduced%npoints
622 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
625 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)))
626 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
628 this%num_symmetry_ops(1:this%reduced%npoints) = num_symm_ops(1:this%reduced%npoints)
629 this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)) = &
630 symm_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops))
632 safe_deallocate_a(num_symm_ops)
633 safe_deallocate_a(symm_ops)
635 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
636 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1))
637 this%num_symmetry_ops(1:this%reduced%npoints) = 1
638 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
639 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
640 do ik = 1, this%full%npoints
641 this%map_full_to_reduced(ik) = ik
643 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
644 this%map_full_to_symidx(:) = 1
647 do ik = 1, this%reduced%npoints
648 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
655 integer(int64) :: dos_method, smearing_function
656 logical :: use_simplex, use_simplex_opt
658 call parse_variable(namespace,
'DOSMethod', option__dosmethod__smear, dos_method)
659 call parse_variable(namespace,
'SmearingFunction', option__smearingfunction__semiconducting, smearing_function)
661 use_simplex = dos_method == option__dosmethod__tetrahedra .or. &
662 smearing_function == option__smearingfunction__tetrahedra
663 use_simplex_opt = dos_method == option__dosmethod__tetrahedra_opt .or. &
664 smearing_function == option__smearingfunction__tetrahedra_opt
666 if (use_simplex .and. use_simplex_opt)
then
667 call messages_not_implemented(
"DOSMethod and SmearingFunction with different tetrahedron methods", namespace=namespace)
670 if (use_simplex .or. use_simplex_opt)
then
671 safe_deallocate_p(this%full%simplex)
672 safe_deallocate_p(this%reduced%simplex)
675 if (use_simplex)
then
676 this%full%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
678 this%reduced%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
679 equiv = this%map_full_to_reduced, opt = .false.)
680 elseif (use_simplex_opt)
then
681 this%full%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
683 this%reduced%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
684 equiv = this%map_full_to_reduced, opt = .
true.)
695 type(namespace_t),
intent(in) :: namespace
696 integer,
intent(in) :: dim
699 integer :: nshifts, nkpoints, nhighsympoints, nsegments
700 integer :: icol, ik, idir, ncols, npoints
701 integer,
allocatable :: resolution(:)
702 real(real64),
allocatable :: highsympoints(:, :)
704 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
732 if (parse_block(namespace,
'KPointsPath', blk) /= 0)
then
733 write(message(1),
'(a)')
'Internal error while reading KPointsPath.'
734 call messages_fatal(1, namespace=namespace)
738 nsegments = parse_block_cols(blk, 0)
739 nhighsympoints = parse_block_n(blk) - 1
740 if (nhighsympoints /= nsegments + 1)
then
741 write(message(1),
'(a,i3,a,i3)')
'The first row of KPointsPath is not compatible with the number of specified k-points.'
742 call messages_fatal(1, namespace=namespace)
745 safe_allocate(resolution(1:nsegments))
746 do icol = 1, nsegments
747 call parse_block_integer(blk, 0, icol-1, resolution(icol))
750 nkpoints = sum(resolution) + 1
752 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
753 do ik = 1, nhighsympoints
754 ncols = parse_block_cols(blk, ik)
755 if (ncols /= dim)
then
756 write(message(1),
'(a,i8,a,i3,a,i3)')
'KPointsPath row ', ik,
' has ', ncols,
' columns but must have ', dim
757 call messages_fatal(1, namespace=namespace)
761 call parse_block_float(blk, ik, idir-1, highsympoints(idir, ik))
765 call parse_block_end(blk)
772 safe_allocate(this%coord_along_path(1:nkpoints))
774 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
775 this%coord_along_path)
777 safe_deallocate_a(resolution)
778 safe_deallocate_a(highsympoints)
783 path_kpoints_grid%weight = m_one/path_kpoints_grid%npoints
785 path_kpoints_grid%weight = m_zero
786 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
790 do ik = 1, path_kpoints_grid%npoints
791 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
798 if (
allocated(this%symmetry_ops))
then
799 npoints = this%reduced%npoints
800 safe_allocate(num_symm_ops(1:npoints))
801 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
803 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
804 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
805 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
811 if (
allocated(this%symmetry_ops))
then
812 safe_deallocate_a(this%num_symmetry_ops)
813 safe_deallocate_a(this%symmetry_ops)
814 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
815 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
817 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
818 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
819 symm_ops(1:npoints, 1:maxval(num_symm_ops))
820 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
821 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
823 safe_deallocate_a(num_symm_ops)
824 safe_deallocate_a(symm_ops)
825 else if(this%use_symmetries)
then
826 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
827 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
829 this%num_symmetry_ops(1:this%reduced%npoints) = 1
830 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
842 type(namespace_t),
intent(in) :: namespace
843 integer,
intent(in) :: dim
848 real(real64) :: weight_sum
886 if (parse_block(namespace,
'KPoints', blk) /= 0)
then
887 if (parse_block(namespace,
'KPointsReduced', blk) == 0)
then
891 write(message(1),
'(a)')
'Internal error loading user-defined k-point list.'
892 call messages_fatal(1, namespace=namespace)
898 user_kpoints_grid%red_point = m_zero
899 user_kpoints_grid%point = m_zero
900 user_kpoints_grid%weight = m_zero
901 user_kpoints_grid%shifts = m_zero
904 do ik = 1, user_kpoints_grid%npoints
905 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
907 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%red_point(idir, ik))
910 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
913 do ik = 1, user_kpoints_grid%npoints
914 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
916 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%point(idir, ik), unit_one/units_inp%length)
919 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
922 call parse_block_end(blk)
925 if (any(user_kpoints_grid%weight < m_epsilon))
then
926 call messages_experimental(
'K-points with zero weight')
927 message(1) =
"Found k-points with zero weight. They are excluded from density calculation"
928 call messages_warning(1, namespace=namespace)
933 do ik=1,user_kpoints_grid%npoints
934 if (user_kpoints_grid%weight(ik) < m_epsilon)
then
936 if (ik < user_kpoints_grid%npoints)
then
937 if (user_kpoints_grid%weight(ik+1) > m_epsilon)
then
938 message(1) =
"K-points with zero weight must follow all regular k-points in a block"
939 call messages_fatal(1, namespace=namespace)
942 this%nik_skip = this%nik_skip + 1
943 user_kpoints_grid%weight(ik) = m_zero
948 weight_sum = sum(user_kpoints_grid%weight)
949 if (weight_sum < m_epsilon)
then
950 message(1) =
"k-point weights must sum to a positive number."
951 call messages_fatal(1, namespace=namespace)
953 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
963 write(message(1),
'(a,i4,a)')
'Input: ', user_kpoints_grid%npoints,
' k-points were read from the input file'
964 call messages_info(1, namespace=namespace)
980 safe_deallocate_a(this%nik_axis)
981 safe_deallocate_a(this%niq_axis)
982 safe_deallocate_a(this%lk123)
983 safe_deallocate_a(this%downsampling)
984 safe_deallocate_a(this%symmetry_ops)
985 safe_deallocate_a(this%num_symmetry_ops)
986 safe_deallocate_a(this%map_full_to_reduced)
987 safe_deallocate_a(this%map_full_to_symidx)
988 safe_deallocate_a(this%coord_along_path)
996 type(namespace_t),
intent(in) :: namespace
998 integer :: idir, is, ik, dim
999 character(len=100) :: str_tmp
1003 dim = this%reduced%dim
1006 write(message(1),
'(a)')
' '
1007 write(message(2),
'(1x,i5,a)') this%reduced%npoints,
' k-points generated from parameters :'
1008 write(message(3),
'(1x,a)')
'---------------------------------------------------'
1009 write(message(4),
'(4x,a)')
'n ='
1011 write(str_tmp,
'(i5)') this%nik_axis(idir)
1012 message(4) = trim(message(4)) // trim(str_tmp)
1014 call messages_info(4, namespace=namespace)
1016 do is = 1, this%reduced%nshifts
1017 write(message(1),
'(a)')
' '
1018 write(message(2),
'(4x,a,i1,a)')
's', is,
' ='
1020 write(str_tmp,
'(f6.2)') this%reduced%shifts(idir,is)
1021 message(2) = trim(message(2)) // trim(str_tmp)
1023 call messages_info(2, namespace=namespace)
1027 write(message(1),
'(a)')
' '
1028 write(message(2),
'(a)')
' index | weight | coordinates |'
1029 call messages_info(2, namespace=namespace)
1031 do ik = 1, this%reduced%npoints
1032 write(str_tmp,
'(i8,a,f12.6,a)') ik,
" | ", this%reduced%weight(ik),
" |"
1033 message(1) = str_tmp
1035 write(str_tmp,
'(f12.6)') this%reduced%red_point(idir, ik)
1036 message(1) = trim(message(1)) // trim(str_tmp)
1038 write(str_tmp,
'(a)')
" |"
1039 message(1) = trim(message(1)) // trim(str_tmp)
1040 call messages_info(1, namespace=namespace)
1043 write(message(1),
'(a)')
' '
1044 call messages_info(1, namespace=namespace)
1052 type(lattice_vectors_t),
intent(in) :: latt
1053 real(real64),
intent(in) :: kin(:)
1054 real(real64),
contiguous,
intent(out) :: kout(:)
1058 kout = matmul(latt%klattice, kin)
1065 type(lattice_vectors_t),
intent(in) :: latt
1066 real(real64),
contiguous,
intent(in) :: kin(:)
1067 real(real64),
contiguous,
intent(out) :: kout(:)
1071 kout = matmul(kin, latt%rlattice) / (m_two*m_pi)
1086 kout%method = kin%method
1091 kout%use_symmetries = kin%use_symmetries
1092 kout%use_time_reversal = kin%use_time_reversal
1094 safe_allocate(kout%nik_axis(1:kin%full%dim))
1095 safe_allocate(kout%niq_axis(1:kin%full%dim))
1096 safe_allocate(kout%downsampling(1:kin%full%dim))
1097 kout%nik_axis(:) = kin%nik_axis(:)
1098 kout%niq_axis(:) = kin%niq_axis(:)
1099 kout%downsampling(:) = kin%downsampling(:)
1101 if (
allocated(kin%lk123))
then
1102 safe_allocate(kout%lk123(1:kin%full%npoints, 1:kin%full%dim))
1103 kout%lk123(:, :) = kin%lk123(:, :)
1106 if (
allocated(kin%coord_along_path))
then
1107 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1108 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1111 if (
allocated(kin%symmetry_ops))
then
1112 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1113 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1114 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1115 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1116 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1118 if (
allocated(kin%map_full_to_symidx))
then
1119 safe_allocate(kout%map_full_to_symidx(1:kin%full%npoints))
1120 kout%map_full_to_symidx(1:kin%full%npoints) = kin%map_full_to_symidx(1:kin%full%npoints)
1122 if (
allocated(kin%map_full_to_reduced))
then
1123 safe_allocate(kout%map_full_to_reduced(1:kin%full%npoints))
1124 kout%map_full_to_reduced(1:kin%full%npoints) = kin%map_full_to_reduced(1:kin%full%npoints)
1132 integer pure function kpoints_number(this) result(number)
1135 number = this%reduced%npoints
1143 integer,
intent(in) :: ik
1144 logical,
optional,
intent(in) :: absolute_coordinates
1145 real(real64) :: point(1:this%full%dim)
1147 if (optional_default(absolute_coordinates, .
true.))
then
1148 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1150 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1159 integer,
intent(in) :: ik
1161 weight = this%reduced%weight(ik)
1177 integer,
intent(in) :: ik
1179 assert(
allocated(this%map_full_to_reduced))
1180 equiv = this%map_full_to_reduced(ik)
1194 integer,
intent(in) :: dim
1195 integer,
intent(in) :: naxis(1:dim)
1196 integer,
intent(in) :: nshifts
1197 real(real64),
intent(in) :: shift(:, :)
1198 real(real64),
contiguous,
intent(out) :: kpoints(:, :)
1199 integer,
contiguous,
optional,
intent(out) :: lk123(:, :)
1202 real(real64) :: dx(dim)
1203 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1204 integer,
allocatable :: lk123_(:, :), idx(:)
1208 dx = m_one/(m_two*naxis)
1210 npoints = product(naxis)
1212 safe_allocate(idx(1:npoints*nshifts))
1213 if (
present(lk123))
then
1214 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1218 do ii = 0, npoints - 1
1219 ik = npoints*is - ii
1224 divisor = divisor / naxis(idir)
1225 ix(idir) = jj / divisor + 1
1226 jj = mod(jj, divisor)
1228 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1232 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64)
then
1233 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1237 if (
present(lk123))
then
1246 if (
present(lk123))
then
1247 do ik = 1, npoints*nshifts
1248 lk123(ik,:) = lk123_(idx(ik),:)
1250 safe_deallocate_a(lk123_)
1253 safe_deallocate_a(idx)
1268 integer,
contiguous,
intent(in ) :: nik_axis(:)
1269 real(real64),
contiguous,
intent(inout) :: kpoints(:, :)
1272 integer,
optional,
intent(in) :: nshifts
1273 integer,
contiguous,
optional,
intent(out) :: indices(:)
1276 integer :: ndim, nk, ik, nshifts_
1277 real(real64) :: dk(size(kpoints, 1))
1278 integer,
allocatable :: idx(:)
1279 real(real64),
allocatable :: shell(:), kpoints_unsorted(:, :)
1283 ndim =
size(kpoints, 1)
1284 nshifts_ = optional_default(nshifts, 1)
1285 nk = product(nik_axis) * nshifts_
1290 dk = m_one / (m_two * nik_axis)
1292 safe_allocate(shell(1:nk))
1293 safe_allocate(idx(1:nk))
1294 safe_allocate_source(kpoints_unsorted(1:ndim, 1:nk), kpoints)
1298 shell(ik) = sum((kpoints_unsorted(:, ik) / dk)**2)
1301 call robust_sort_by_abs(shell, kpoints_unsorted, idx)
1302 safe_deallocate_a(shell)
1305 kpoints(:, ik) = kpoints_unsorted(:, idx(ik))
1308 if (
present(indices)) indices = idx
1310 safe_deallocate_a(idx)
1311 safe_deallocate_a(kpoints_unsorted)
1319 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1320 integer,
intent(in) :: dim
1321 type(lattice_vectors_t),
intent(in) :: latt
1322 integer,
intent(in) :: nkpoints
1323 integer,
intent(in) :: nsegments
1324 integer,
contiguous,
intent(in) :: resolution(:)
1325 real(real64),
contiguous,
intent(in) :: highsympoints(:,:)
1326 real(real64),
intent(out) :: kpoints(1:dim, 1:nkpoints)
1327 real(real64),
intent(out) :: coord(1:nkpoints)
1329 integer :: is, ik, kpt_ind
1330 real(real64) :: length, total_length, accumulated_length
1331 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1335 total_length = m_zero
1336 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1338 do is = 1, nsegments
1345 if (resolution(is) > 0) total_length = total_length + length
1348 accumulated_length = m_zero
1351 do is = 1, nsegments
1358 if (length > m_epsilon) vec = vec/length
1360 do ik = 1, resolution(is)
1361 kpt_ind = kpt_ind +1
1362 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1363 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1365 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1368 kpt_ind = kpt_ind +1
1370 coord(kpt_ind) = accumulated_length
1371 kpoints(:, kpt_ind) = kpt1
1374 coord = coord/total_length
1382 map_full_to_reduced, map_full_to_symidx, symm_ops, num_symm_ops)
1383 type(symmetries_t),
intent(in) :: symm
1384 logical,
intent(in) :: time_reversal
1385 integer,
intent(inout) :: nkpoints
1386 integer,
intent(in) :: dim
1387 real(real64),
intent(inout) :: kpoints(1:dim,1:nkpoints)
1388 real(real64),
intent(out) :: weights(1:nkpoints)
1389 integer,
intent(out) :: map_full_to_reduced(1:nkpoints)
1390 integer,
intent(out) :: map_full_to_symidx(1:nkpoints)
1391 integer,
contiguous,
intent(out) :: symm_ops(:, :)
1392 integer,
contiguous,
intent(out) :: num_symm_ops(:)
1395 real(real64),
allocatable :: reduced(:, :)
1397 integer ik, iop, ik2
1398 real(real64) :: tran(dim), diff(dim)
1399 real(real64),
allocatable :: kweight(:)
1401 real(real64) :: prec
1408 prec = min(symprec, m_one/(nkpoints*100))
1415 safe_allocate(kweight(1:nkpoints))
1416 safe_allocate(reduced(1:dim, 1:nkpoints))
1418 kweight = m_one / nkpoints
1421 map_full_to_reduced(:) = -1
1422 map_full_to_symidx(:) = -1
1425 symm_ops(:, 1) = symmetries_identity_index(symm)
1428 if (kweight(ik) < prec) cycle
1432 nreduced = nreduced + 1
1433 reduced(:, nreduced) = kpoints(:, ik)
1434 map_full_to_reduced(ik) = nreduced
1435 map_full_to_symidx(ik) = 1
1438 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1440 if (ik == nkpoints) cycle
1443 do iop = 1, symmetries_number(symm)
1444 if (iop == symmetries_identity_index(symm) .and. &
1445 .not. time_reversal) cycle
1447 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1449 tran = tran - anint(tran + m_half*prec)
1452 do ik2 = ik + 1, nkpoints
1453 if (kweight(ik2) < prec) cycle
1455 if (.not. iop == symmetries_identity_index(symm))
then
1456 diff = tran - kpoints(:, ik2)
1457 diff = diff - anint(diff)
1460 if (sum(abs(diff)) < prec)
then
1461 kweight(ik) = kweight(ik) + kweight(ik2)
1462 kweight(ik2) = m_zero
1463 map_full_to_reduced(ik2) = nreduced
1464 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1465 weights(nreduced) = kweight(ik)
1466 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1467 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1472 if (time_reversal)
then
1473 diff = tran + kpoints(:, ik2)
1474 diff = diff - anint(diff)
1477 if (sum(abs(diff)) < prec)
then
1478 kweight(ik) = kweight(ik) + kweight(ik2)
1479 kweight(ik2) = m_zero
1480 map_full_to_reduced(ik2) = nreduced
1481 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1482 weights(nreduced) = kweight(ik)
1483 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1485 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1492 assert(sum(weights(1:nreduced)) - m_one < prec)
1493 assert(all(1 <= map_full_to_reduced(:)) .and. all(map_full_to_reduced(:) <= nreduced))
1494 assert(all(1 <= map_full_to_symidx(:)) .and. all(map_full_to_symidx(:) <=
size(symm_ops, 2)))
1498 kpoints(:, ik) = reduced(:, ik)
1501 safe_deallocate_a(kweight)
1502 safe_deallocate_a(reduced)
1511 type(lattice_vectors_t),
intent(in) :: latt
1513 integer :: ig1, ig2, ik
1514 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1515 real(real64) :: vec(grid%dim), kpt(grid%dim)
1516 real(real64) :: d, dmin
1521 do ig1 = 1, grid%dim
1522 do ig2 = 1, 3**grid%dim
1523 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1527 do ig1 = 1, 3**grid%dim
1531 do ik = 1, grid%npoints
1534 do ig1 = 1, 3**grid%dim
1535 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1536 d = real(sum(vec**2), real32)
1543 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1554 integer,
optional,
intent(in) :: iunit
1555 type(namespace_t),
optional,
intent(in) :: namespace
1556 logical,
optional,
intent(in) :: absolute_coordinates
1559 character(len=100) :: str_tmp
1564 call messages_print_with_emphasis(
'Brillouin zone sampling', iunit, namespace)
1568 call messages_write(
'Dimensions of the k-point grid =')
1569 do idir = 1, this%full%dim
1570 call messages_write(this%nik_axis(idir), fmt =
'(i3,1x)')
1572 call messages_new_line()
1574 if (.not. all(this%downsampling(1:this%full%dim) == 1))
then
1575 call messages_write(
'Dimensions of the q-point grid =')
1576 do idir = 1, this%full%dim
1577 call messages_write(this%niq_axis(idir), fmt =
'(i3,1x)')
1579 call messages_new_line()
1582 call messages_write(
'Total number of k-points =')
1583 call messages_write(this%full%npoints)
1584 call messages_new_line()
1586 call messages_write(
'Number of symmetry-reduced k-points =')
1587 call messages_write(this%reduced%npoints)
1589 call messages_info(iunit=iunit, namespace=namespace)
1593 call messages_write(
'Total number of k-points =')
1594 call messages_write(this%full%npoints)
1595 call messages_new_line()
1596 call messages_info(iunit=iunit, namespace=namespace)
1600 call messages_new_line()
1601 call messages_write(
'List of k-points:')
1602 call messages_info(iunit=iunit, namespace=namespace)
1604 write(message(1),
'(6x,a)')
'ik'
1605 do idir = 1, this%full%dim
1606 index = index2axis(idir)
1607 write(str_tmp,
'(9x,2a)')
'k_', index
1608 message(1) = trim(message(1)) // trim(str_tmp)
1610 write(str_tmp,
'(6x,a)')
'Weight'
1611 message(1) = trim(message(1)) // trim(str_tmp)
1612 message(2) =
'---------------------------------------------------------'
1613 call messages_info(2, iunit)
1616 write(message(1),
'(i8,1x)') ik
1617 do idir = 1, this%full%dim
1618 if (optional_default(absolute_coordinates, .false.))
then
1619 write(str_tmp,
'(f12.4)') this%reduced%point(idir, ik)
1621 write(str_tmp,
'(f12.4)') this%reduced%red_point(idir, ik)
1623 message(1) = trim(message(1)) // trim(str_tmp)
1626 message(1) = trim(message(1)) // trim(str_tmp)
1627 call messages_info(1, iunit, namespace=namespace)
1630 call messages_info(iunit=iunit, namespace=namespace)
1632 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1641 integer,
intent(in) :: ik
1649 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1651 integer,
intent(in) :: ik
1653 if (this%use_symmetries)
then
1654 num = this%num_symmetry_ops(ik)
1662 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1664 integer,
intent(in) :: ik
1665 integer,
intent(in) :: index
1667 if (this%use_symmetries)
then
1668 iop = this%symmetry_ops(ik, index)
1685 integer pure function kpoints_get_full_symmetry_op_index(this, ifull) result(iiop)
1687 integer,
intent(in) :: ifull
1689 if (this%use_symmetries)
then
1690 iiop = this%map_full_to_symidx(ifull)
1698 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1700 integer,
intent(in) :: ik
1701 integer,
intent(in) :: index
1706 if (this%use_symmetries)
then
1707 do iop = 1, this%num_symmetry_ops(ik)
1708 if (this%symmetry_ops(ik, iop) == index)
then
1724 integer :: denom, nik, nik_skip
1728 nik = this%full%npoints
1729 nik_skip = this%nik_skip
1736 do denom = 1, 100000
1737 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1738 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon))
then
1752 if (this%nik_skip > 0)
then
1755 have_zerow = .false.
1770 integer,
intent(in) :: ind
1772 coord = this%coord_along_path(ind)
1780 type(symmetries_t),
intent(in) :: symm
1781 integer,
intent(in) :: dim
1782 logical,
intent(in) :: time_reversal
1783 type(mpi_grp_t),
intent(in) :: grp
1784 type(namespace_t),
intent(in) :: namespace
1786 integer,
allocatable :: kmap(:)
1787 real(real64) :: kpt(dim), diff(dim)
1788 integer :: nk, ik, ik2, iop
1789 type(distributed_t) :: kpt_dist
1796 call distributed_init(kpt_dist, nk, grp%comm,
"kpt_check")
1799 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1801 do iop = 1, symmetries_number(symm)
1802 if (iop == symmetries_identity_index(symm) .and. &
1803 .not. time_reversal) cycle
1805 do ik = kpt_dist%start, kpt_dist%end
1809 do ik = kpt_dist%start, kpt_dist%end
1811 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1813 kpt = kpt - anint(kpt + m_half*symprec)
1818 if (iop /= symmetries_identity_index(symm))
then
1819 diff = kpt - grid%red_point(:, ik2)
1820 diff = diff - anint(diff)
1822 if (sum(abs(diff)) < symprec)
then
1828 if (time_reversal)
then
1829 diff = kpt + grid%red_point(:, ik2)
1830 diff = diff - anint(diff)
1832 if (sum(abs(diff)) < symprec)
then
1840 if (kmap(ik) == ik)
then
1841 write(message(1),
'(a,i5,a2,3(f7.3,a2),a)')
"The reduced k-point ", ik,
" (", &
1842 grid%red_point(1, ik),
", ", grid%red_point(2, ik),
", ", grid%red_point(3, ik), &
1843 ") ",
"has no symmetric in the k-point grid for the following symmetry"
1844 write(message(2),
'(i5,1x,a,2x,3(3i4,2x))') iop,
':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1845 message(3) =
"Change your k-point grid or use KPointsUseSymmetries=no."
1846 call messages_fatal(3, namespace=namespace)
1851 safe_deallocate_a(kmap)
1853 call distributed_end(kpt_dist)
1861 integer,
intent(in) :: ik
1862 integer,
intent(in) :: iq
1864 integer :: dim, idim
1865 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1870 dim = kpt%reduced%dim
1873 if (all(kpt%downsampling == 1))
then
1880 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1883 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1884 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1885 if (abs(red(idim) - anint(red(idim))) > m_epsilon)
then
1886 compatible = .false.
1900 if (
allocated(this%coord_along_path))
then
1901 npath =
SIZE(this%coord_along_path)
1920 type(lattice_vectors_t),
intent(in) :: new_latt
1926 this%latt = new_latt
1928 do ik = 1, this%reduced%npoints
1929 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1932 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)
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)
subroutine, public kpoints_init(this, namespace, symm, dim, periodic_dim, latt, grp)
integer function kpoints_get_equiv(this, ik)
Map a full-grid k-point index to its reduced-grid representative.
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_read_mp(this, namespace, symm, dim, grp, gamma_only)
Read a Monkhorst-Pack k-point grid and initialize the base k-point data.
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 kpoints_check_symmetries(grid, symm, dim, time_reversal, grp, namespace)
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.
This is defined even when running serial.