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,
private :: symmetry_ops(:, :)
105 integer,
allocatable,
private :: num_symmetry_ops(:)
106 integer,
allocatable,
private :: map_full_to_reduced(:)
107 integer,
allocatable,
private :: map_full_to_symidx(:)
110 real(real64),
allocatable,
private :: coord_along_path(:)
112 integer,
allocatable :: downsampling(:)
114 type(symmetries_t),
pointer :: symm => null()
128 integer,
public,
parameter :: &
138 integer,
intent(in) :: dim
139 type(kpoints_grid_t),
intent(out) :: this
140 integer,
intent(in) :: npoints
141 integer,
intent(in) :: nshifts
146 this%npoints = npoints
147 this%nshifts = nshifts
148 safe_allocate(this%red_point(1:dim, 1:npoints))
149 safe_allocate(this%point(1:dim, 1:npoints))
150 safe_allocate(this%point1bz(1:dim,1:npoints))
151 safe_allocate(this%weight(1:npoints))
152 safe_allocate(this%shifts(1:dim,1:nshifts))
159 type(kpoints_grid_t),
intent(inout) :: this
163 safe_deallocate_a(this%red_point)
164 safe_deallocate_a(this%point)
165 safe_deallocate_a(this%point1BZ)
166 safe_deallocate_a(this%weight)
167 safe_deallocate_a(this%shifts)
168 safe_deallocate_p(this%simplex)
182 aa%weight(1:bb%npoints) = bb%weight(1:bb%npoints)
183 aa%point(1:bb%dim, 1:bb%npoints) = bb%point(1:bb%dim, 1:bb%npoints)
184 aa%point1BZ(1:bb%dim, 1:bb%npoints) = bb%point1BZ(1:bb%dim, 1:bb%npoints)
185 aa%red_point(1:bb%dim, 1:bb%npoints) = bb%red_point(1:bb%dim, 1:bb%npoints)
186 aa%shifts(1:bb%dim, 1:bb%nshifts) = bb%shifts(1:bb%dim, 1:bb%nshifts)
200 if (.not.
allocated(that%point))
then
205 if (.not.
allocated(this%point))
then
222 this%red_point(1:old_grid%dim, 1:old_grid%npoints)= old_grid%red_point(1:old_grid%dim, 1:old_grid%npoints)
223 this%point(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point(1:old_grid%dim, 1:old_grid%npoints)
224 this%point1BZ(1:old_grid%dim, 1:old_grid%npoints) = old_grid%point1BZ(1:old_grid%dim, 1:old_grid%npoints)
225 this%weight(1:old_grid%npoints) = old_grid%weight(1:old_grid%npoints)
226 this%shifts(1:old_grid%dim, 1:old_grid%nshifts) = old_grid%shifts(1:old_grid%dim, 1:old_grid%nshifts)
229 this%red_point(1:old_grid%dim, old_grid%npoints+1:this%npoints)= that%red_point(1:that%dim, 1:that%npoints)
230 this%point(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point(1:that%dim, 1:that%npoints)
231 this%point1BZ(1:old_grid%dim, old_grid%npoints+1:this%npoints) = that%point1BZ(1:that%dim, 1:that%npoints)
232 this%weight(old_grid%npoints+1:this%npoints) = that%weight(1:that%npoints)
244 logical,
intent(in) :: use_symmetries
245 logical,
intent(in) :: only_gamma
254 method = kpoints_gamma
267 if (use_symmetries)
then
268 write(
message(1),
'(a)')
"User-defined k-points are not compatible with KPointsUseSymmetries=yes."
276 if (use_symmetries)
then
277 write(
message(1),
'(a)')
"KPointsPath is not compatible with KPointsUseSymmetries=yes."
282 if (method == 0)
then
283 write(
message(1),
'(a)')
"Unable to determine the method for defining k-points."
284 write(
message(2),
'(a)')
"Octopus will continue assuming a Monkhorst Pack grid."
297 integer,
intent(in) :: dim
305 safe_allocate(this%nik_axis(1:dim))
306 safe_allocate(this%niq_axis(1:dim))
307 safe_allocate(this%downsampling(1:dim))
311 this%downsampling = 1
313 safe_deallocate_a(this%map_full_to_reduced)
314 safe_deallocate_a(this%map_full_to_symidx)
320 subroutine kpoints_init(this, namespace, symm, dim, periodic_dim, latt)
324 integer,
intent(in) :: dim
325 integer,
intent(in) :: periodic_dim
328 logical :: only_gamma, default_timereversal
349 call parse_variable(namespace,
'KPointsUseSymmetries', .false., this%use_symmetries)
369 call parse_variable(namespace,
'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
371 only_gamma = (periodic_dim == 0)
403 integer,
intent(in) :: dim
404 logical,
intent(in) :: gamma_only
406 logical :: gamma_only_
407 integer :: ii, ik, is, ncols, nshifts
409 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
410 real(real64),
allocatable :: shifts(:, :)
458 gamma_only_ = gamma_only
459 if (.not. gamma_only_)
then
460 gamma_only_ = (
parse_block(namespace,
'KPointsGrid', blk) /= 0)
465 if (.not. gamma_only_)
then
470 safe_allocate(shifts(1:dim,1:nshifts))
473 if (.not. gamma_only_)
then
475 if (ncols /= dim)
then
476 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid first row has ', ncols,
' columns but should have ', dim
477 if (ncols < dim)
then
480 write(
message(2),
'(a)')
'Continuing, but ignoring the additional values.'
488 if (any(this%nik_axis < 1))
then
489 message(1) =
'Input: KPointsGrid is not valid.'
495 if (ncols /= dim)
then
496 write(
message(1),
'(a,i3,a,i3)')
'KPointsGrid shift has ', ncols,
' columns but must have ', dim
507 if (mod(this%nik_axis(ii), 2) /= 0)
then
537 this%niq_axis(:) = this%nik_axis(:)
538 this%downsampling(:) = 1
540 if (
parse_block(namespace,
'QPointsGrid', blk) == 0)
then
542 if (ncols /= dim)
then
543 write(
message(1),
'(a,i3,a,i3)')
'QPointsGrid first row has ', ncols,
' columns but must have ', dim
550 if (any(this%nik_axis/this%niq_axis /= nint(this%nik_axis/real(this%niq_axis))))
then
551 message(1) =
'Input: QPointsGrid is not compatible with the KPointsGrid.'
555 this%downsampling = this%nik_axis/this%niq_axis
557 if (any(this%downsampling /= 1) .and. this%use_symmetries)
then
568 this%full%shifts(:, :) = shifts(:, :)
569 safe_deallocate_a(shifts)
571 call kpoints_grid_generate(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point)
573 do ik = 1, this%full%npoints
577 this%full%weight =
m_one / this%full%npoints
579 if (this%use_symmetries)
then
580 message(1) =
"Checking if the generated full k-point grid is symmetric"
587 if (this%use_symmetries)
then
588 safe_allocate(num_symm_ops(1:this%full%npoints))
590 if (this%use_time_reversal)
then
596 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
597 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
599 this%reduced%npoints, dim, this%reduced%red_point, this%reduced%weight, this%map_full_to_reduced, &
600 this%map_full_to_symidx, symm_ops, num_symm_ops)
602 assert(maxval(num_symm_ops) >= 1)
603 if (this%use_time_reversal)
then
610 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
612 do ik = 1, this%reduced%npoints
613 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
616 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)))
617 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
619 this%num_symmetry_ops(1:this%reduced%npoints) = num_symm_ops(1:this%reduced%npoints)
620 this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)) = &
621 symm_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops))
623 safe_deallocate_a(num_symm_ops)
624 safe_deallocate_a(symm_ops)
626 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
627 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1))
628 this%num_symmetry_ops(1:this%reduced%npoints) = 1
629 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
630 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
631 do ik = 1, this%full%npoints
632 this%map_full_to_reduced(ik) = ik
634 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
635 this%map_full_to_symidx(:) = 1
638 do ik = 1, this%reduced%npoints
639 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
646 integer(int64) :: dos_method, smearing_function
647 logical :: use_simplex, use_simplex_opt
649 call parse_variable(namespace,
'DOSMethod', option__dosmethod__smear, dos_method)
650 call parse_variable(namespace,
'SmearingFunction', option__smearingfunction__semiconducting, smearing_function)
652 use_simplex = dos_method == option__dosmethod__tetrahedra .or. &
653 smearing_function == option__smearingfunction__tetrahedra
654 use_simplex_opt = dos_method == option__dosmethod__tetrahedra_opt .or. &
655 smearing_function == option__smearingfunction__tetrahedra_opt
657 if (use_simplex .and. use_simplex_opt)
then
658 call messages_not_implemented(
"DOSMethod and SmearingFunction with different tetrahedron methods", namespace=namespace)
661 if (use_simplex .or. use_simplex_opt)
then
662 safe_deallocate_p(this%full%simplex)
663 safe_deallocate_p(this%reduced%simplex)
666 if (use_simplex)
then
667 this%full%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
669 this%reduced%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
670 equiv = this%map_full_to_reduced, opt = .false.)
671 elseif (use_simplex_opt)
then
672 this%full%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
674 this%reduced%simplex =>
simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
675 equiv = this%map_full_to_reduced, opt = .
true.)
686 type(namespace_t),
intent(in) :: namespace
687 integer,
intent(in) :: dim
690 integer :: nshifts, nkpoints, nhighsympoints, nsegments
691 integer :: icol, ik, idir, ncols, npoints
692 integer,
allocatable :: resolution(:)
693 real(real64),
allocatable :: highsympoints(:, :)
695 integer,
allocatable :: symm_ops(:, :), num_symm_ops(:)
723 if (parse_block(namespace,
'KPointsPath', blk) /= 0)
then
724 write(message(1),
'(a)')
'Internal error while reading KPointsPath.'
725 call messages_fatal(1, namespace=namespace)
729 nsegments = parse_block_cols(blk, 0)
730 nhighsympoints = parse_block_n(blk) - 1
731 if (nhighsympoints /= nsegments + 1)
then
732 write(message(1),
'(a,i3,a,i3)')
'The first row of KPointsPath is not compatible with the number of specified k-points.'
733 call messages_fatal(1, namespace=namespace)
736 safe_allocate(resolution(1:nsegments))
737 do icol = 1, nsegments
738 call parse_block_integer(blk, 0, icol-1, resolution(icol))
741 nkpoints = sum(resolution) + 1
743 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
744 do ik = 1, nhighsympoints
745 ncols = parse_block_cols(blk, ik)
746 if (ncols /= dim)
then
747 write(message(1),
'(a,i8,a,i3,a,i3)')
'KPointsPath row ', ik,
' has ', ncols,
' columns but must have ', dim
748 call messages_fatal(1, namespace=namespace)
752 call parse_block_float(blk, ik, idir-1, highsympoints(idir, ik))
756 call parse_block_end(blk)
763 safe_allocate(this%coord_along_path(1:nkpoints))
765 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
766 this%coord_along_path)
768 safe_deallocate_a(resolution)
769 safe_deallocate_a(highsympoints)
774 path_kpoints_grid%weight = m_one/path_kpoints_grid%npoints
776 path_kpoints_grid%weight = m_zero
777 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
781 do ik = 1, path_kpoints_grid%npoints
782 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
789 if (
allocated(this%symmetry_ops))
then
790 npoints = this%reduced%npoints
791 safe_allocate(num_symm_ops(1:npoints))
792 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
794 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
795 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
796 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
802 if (
allocated(this%symmetry_ops))
then
803 safe_deallocate_a(this%num_symmetry_ops)
804 safe_deallocate_a(this%symmetry_ops)
805 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
806 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
808 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
809 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
810 symm_ops(1:npoints, 1:maxval(num_symm_ops))
811 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
812 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
814 safe_deallocate_a(num_symm_ops)
815 safe_deallocate_a(symm_ops)
816 else if(this%use_symmetries)
then
817 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
818 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
820 this%num_symmetry_ops(1:this%reduced%npoints) = 1
821 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
833 type(namespace_t),
intent(in) :: namespace
834 integer,
intent(in) :: dim
839 real(real64) :: weight_sum
877 if (parse_block(namespace,
'KPoints', blk) /= 0)
then
878 if (parse_block(namespace,
'KPointsReduced', blk) == 0)
then
882 write(message(1),
'(a)')
'Internal error loading user-defined k-point list.'
883 call messages_fatal(1, namespace=namespace)
889 user_kpoints_grid%red_point = m_zero
890 user_kpoints_grid%point = m_zero
891 user_kpoints_grid%weight = m_zero
892 user_kpoints_grid%shifts = m_zero
895 do ik = 1, user_kpoints_grid%npoints
896 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
898 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%red_point(idir, ik))
901 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
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%point(idir, ik), unit_one/units_inp%length)
910 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
913 call parse_block_end(blk)
916 if (any(user_kpoints_grid%weight < m_epsilon))
then
917 call messages_experimental(
'K-points with zero weight')
918 message(1) =
"Found k-points with zero weight. They are excluded from density calculation"
919 call messages_warning(1, namespace=namespace)
924 do ik=1,user_kpoints_grid%npoints
925 if (user_kpoints_grid%weight(ik) < m_epsilon)
then
927 if (ik < user_kpoints_grid%npoints)
then
928 if (user_kpoints_grid%weight(ik+1) > m_epsilon)
then
929 message(1) =
"K-points with zero weight must follow all regular k-points in a block"
930 call messages_fatal(1, namespace=namespace)
933 this%nik_skip = this%nik_skip + 1
934 user_kpoints_grid%weight(ik) = m_zero
939 weight_sum = sum(user_kpoints_grid%weight)
940 if (weight_sum < m_epsilon)
then
941 message(1) =
"k-point weights must sum to a positive number."
942 call messages_fatal(1, namespace=namespace)
944 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
954 write(message(1),
'(a,i4,a)')
'Input: ', user_kpoints_grid%npoints,
' k-points were read from the input file'
955 call messages_info(1, namespace=namespace)
971 safe_deallocate_a(this%nik_axis)
972 safe_deallocate_a(this%niq_axis)
973 safe_deallocate_a(this%downsampling)
974 safe_deallocate_a(this%symmetry_ops)
975 safe_deallocate_a(this%num_symmetry_ops)
976 safe_deallocate_a(this%map_full_to_reduced)
977 safe_deallocate_a(this%map_full_to_symidx)
978 safe_deallocate_a(this%coord_along_path)
986 type(namespace_t),
intent(in) :: namespace
988 integer :: idir, is, ik, dim
989 character(len=100) :: str_tmp
993 dim = this%reduced%dim
996 write(message(1),
'(a)')
' '
997 write(message(2),
'(1x,i5,a)') this%reduced%npoints,
' k-points generated from parameters :'
998 write(message(3),
'(1x,a)')
'---------------------------------------------------'
999 write(message(4),
'(4x,a)')
'n ='
1001 write(str_tmp,
'(i5)') this%nik_axis(idir)
1002 message(4) = trim(message(4)) // trim(str_tmp)
1004 call messages_info(4, namespace=namespace)
1006 do is = 1, this%reduced%nshifts
1007 write(message(1),
'(a)')
' '
1008 write(message(2),
'(4x,a,i1,a)')
's', is,
' ='
1010 write(str_tmp,
'(f6.2)') this%reduced%shifts(idir,is)
1011 message(2) = trim(message(2)) // trim(str_tmp)
1013 call messages_info(2, namespace=namespace)
1017 write(message(1),
'(a)')
' '
1018 write(message(2),
'(a)')
' index | weight | coordinates |'
1019 call messages_info(2, namespace=namespace)
1021 do ik = 1, this%reduced%npoints
1022 write(str_tmp,
'(i8,a,f12.6,a)') ik,
" | ", this%reduced%weight(ik),
" |"
1023 message(1) = str_tmp
1025 write(str_tmp,
'(f12.6)') this%reduced%red_point(idir, ik)
1026 message(1) = trim(message(1)) // trim(str_tmp)
1028 write(str_tmp,
'(a)')
" |"
1029 message(1) = trim(message(1)) // trim(str_tmp)
1030 call messages_info(1, namespace=namespace)
1033 write(message(1),
'(a)')
' '
1034 call messages_info(1, namespace=namespace)
1042 type(lattice_vectors_t),
intent(in) :: latt
1043 real(real64),
intent(in) :: kin(:)
1044 real(real64),
intent(out) :: kout(:)
1048 kout = matmul(latt%klattice, kin)
1055 type(lattice_vectors_t),
intent(in) :: latt
1056 real(real64),
intent(in) :: kin(:)
1057 real(real64),
intent(out) :: kout(:)
1061 kout = matmul(kin, latt%rlattice) / (m_two*m_pi)
1076 kout%method = kin%method
1081 kout%use_symmetries = kin%use_symmetries
1082 kout%use_time_reversal = kin%use_time_reversal
1084 safe_allocate(kout%nik_axis(1:kin%full%dim))
1085 safe_allocate(kout%niq_axis(1:kin%full%dim))
1086 safe_allocate(kout%downsampling(1:kin%full%dim))
1087 kout%nik_axis(:) = kin%nik_axis(:)
1088 kout%niq_axis(:) = kin%niq_axis(:)
1089 kout%downsampling(:) = kin%downsampling(:)
1091 if (
allocated(kin%coord_along_path))
then
1092 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1093 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1096 if (
allocated(kin%symmetry_ops))
then
1097 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1098 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1099 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1100 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1101 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1103 if (
allocated(kin%map_full_to_symidx))
then
1104 safe_allocate(kout%map_full_to_symidx(1:kin%full%npoints))
1105 kout%map_full_to_symidx(1:kin%full%npoints) = kin%map_full_to_symidx(1:kin%full%npoints)
1107 if (
allocated(kin%map_full_to_reduced))
then
1108 safe_allocate(kout%map_full_to_reduced(1:kin%full%npoints))
1109 kout%map_full_to_reduced(1:kin%full%npoints) = kin%map_full_to_reduced(1:kin%full%npoints)
1117 integer pure function kpoints_number(this) result(number)
1120 number = this%reduced%npoints
1128 integer,
intent(in) :: ik
1129 logical,
optional,
intent(in) :: absolute_coordinates
1130 real(real64) :: point(1:this%full%dim)
1132 if (optional_default(absolute_coordinates, .
true.))
then
1133 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1135 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1144 integer,
intent(in) :: ik
1146 weight = this%reduced%weight(ik)
1162 integer,
intent(in) :: ik
1164 assert(
allocated(this%map_full_to_reduced))
1165 equiv = this%map_full_to_reduced(ik)
1179 integer,
intent(in) :: dim
1180 integer,
intent(in) :: naxis(1:dim)
1181 integer,
intent(in) :: nshifts
1182 real(real64),
intent(in) :: shift(:, :)
1183 real(real64),
intent(out) :: kpoints(:, :)
1184 integer,
optional,
intent(out) :: lk123(:, :)
1187 real(real64) :: dx(dim)
1188 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1189 integer,
allocatable :: lk123_(:, :), idx(:)
1193 dx = m_one/(m_two*naxis)
1195 npoints = product(naxis)
1197 safe_allocate(idx(1:npoints*nshifts))
1198 if (
present(lk123))
then
1199 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1203 do ii = 0, npoints - 1
1204 ik = npoints*is - ii
1209 divisor = divisor / naxis(idir)
1210 ix(idir) = jj / divisor + 1
1211 jj = mod(jj, divisor)
1213 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1217 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64)
then
1218 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1222 if (
present(lk123))
then
1231 if (
present(lk123))
then
1232 do ik = 1, npoints*nshifts
1233 lk123(ik,:) = lk123_(idx(ik),:)
1235 safe_deallocate_a(lk123_)
1238 safe_deallocate_a(idx)
1253 integer,
intent(in ) :: nik_axis(:)
1254 real(real64),
intent(inout) :: kpoints(:, :)
1257 integer,
optional,
intent(in) :: nshifts
1258 integer,
optional,
intent(out) :: indices(:)
1261 integer :: ndim, nk, ik, nshifts_
1262 real(real64) :: dk(size(kpoints, 1))
1263 integer,
allocatable :: idx(:)
1264 real(real64),
allocatable :: shell(:), kpoints_unsorted(:, :)
1268 ndim =
size(kpoints, 1)
1269 nshifts_ = optional_default(nshifts, 1)
1270 nk = product(nik_axis) * nshifts_
1275 dk = m_one / (m_two * nik_axis)
1277 safe_allocate(shell(1:nk))
1278 safe_allocate(idx(1:nk))
1279 safe_allocate_source(kpoints_unsorted(1:ndim, 1:nk), kpoints)
1283 shell(ik) = sum((kpoints_unsorted(:, ik) / dk)**2)
1286 call robust_sort_by_abs(shell, kpoints_unsorted, idx)
1287 safe_deallocate_a(shell)
1290 kpoints(:, ik) = kpoints_unsorted(:, idx(ik))
1293 if (
present(indices)) indices = idx
1295 safe_deallocate_a(idx)
1296 safe_deallocate_a(kpoints_unsorted)
1304 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1305 integer,
intent(in) :: dim
1306 type(lattice_vectors_t),
intent(in) :: latt
1307 integer,
intent(in) :: nkpoints
1308 integer,
intent(in) :: nsegments
1309 integer,
intent(in) :: resolution(:)
1310 real(real64),
intent(in) :: highsympoints(:,:)
1311 real(real64),
intent(out) :: kpoints(1:dim, 1:nkpoints)
1312 real(real64),
intent(out) :: coord(1:nkpoints)
1314 integer :: is, ik, kpt_ind
1315 real(real64) :: length, total_length, accumulated_length
1316 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1320 total_length = m_zero
1321 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1323 do is = 1, nsegments
1330 if (resolution(is) > 0) total_length = total_length + length
1333 accumulated_length = m_zero
1336 do is = 1, nsegments
1345 do ik = 1, resolution(is)
1346 kpt_ind = kpt_ind +1
1347 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1348 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1350 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1353 kpt_ind = kpt_ind +1
1355 coord(kpt_ind) = accumulated_length
1356 kpoints(:, kpt_ind) = kpt1
1359 coord = coord/total_length
1367 map_full_to_reduced, map_full_to_symidx, symm_ops, num_symm_ops)
1368 type(symmetries_t),
intent(in) :: symm
1369 logical,
intent(in) :: time_reversal
1370 integer,
intent(inout) :: nkpoints
1371 integer,
intent(in) :: dim
1372 real(real64),
intent(inout) :: kpoints(1:dim,1:nkpoints)
1373 real(real64),
intent(out) :: weights(1:nkpoints)
1374 integer,
intent(out) :: map_full_to_reduced(1:nkpoints)
1375 integer,
intent(out) :: map_full_to_symidx(1:nkpoints)
1376 integer,
intent(out) :: symm_ops(:, :)
1377 integer,
intent(out) :: num_symm_ops(:)
1380 real(real64),
allocatable :: reduced(:, :)
1382 integer ik, iop, ik2
1383 real(real64) :: tran(dim), diff(dim)
1384 real(real64),
allocatable :: kweight(:)
1386 real(real64) :: prec
1393 prec = min(symprec, m_one/(nkpoints*100))
1400 safe_allocate(kweight(1:nkpoints))
1401 safe_allocate(reduced(1:dim, 1:nkpoints))
1403 kweight = m_one / nkpoints
1406 map_full_to_reduced(:) = -1
1407 map_full_to_symidx(:) = -1
1410 symm_ops(:, 1) = symmetries_identity_index(symm)
1413 if (kweight(ik) < prec) cycle
1417 nreduced = nreduced + 1
1418 reduced(:, nreduced) = kpoints(:, ik)
1419 map_full_to_reduced(ik) = nreduced
1420 map_full_to_symidx(ik) = 1
1423 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1425 if (ik == nkpoints) cycle
1428 do iop = 1, symmetries_number(symm)
1429 if (iop == symmetries_identity_index(symm) .and. &
1430 .not. time_reversal) cycle
1432 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1434 tran = tran - anint(tran + m_half*prec)
1437 do ik2 = ik + 1, nkpoints
1438 if (kweight(ik2) < prec) cycle
1440 if (.not. iop == symmetries_identity_index(symm))
then
1441 diff = tran - kpoints(:, ik2)
1442 diff = diff - anint(diff)
1445 if (sum(abs(diff)) < prec)
then
1446 kweight(ik) = kweight(ik) + kweight(ik2)
1447 kweight(ik2) = m_zero
1448 map_full_to_reduced(ik2) = nreduced
1449 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1450 weights(nreduced) = kweight(ik)
1451 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1452 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1457 if (time_reversal)
then
1458 diff = tran + kpoints(:, ik2)
1459 diff = diff - anint(diff)
1462 if (sum(abs(diff)) < prec)
then
1463 kweight(ik) = kweight(ik) + kweight(ik2)
1464 kweight(ik2) = m_zero
1465 map_full_to_reduced(ik2) = nreduced
1466 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1467 weights(nreduced) = kweight(ik)
1468 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1470 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1477 assert(sum(weights(1:nreduced)) - m_one < prec)
1478 assert(all(1 <= map_full_to_reduced(:)) .and. all(map_full_to_reduced(:) <= nreduced))
1479 assert(all(1 <= map_full_to_symidx(:)) .and. all(map_full_to_symidx(:) <=
size(symm_ops, 2)))
1483 kpoints(:, ik) = reduced(:, ik)
1486 safe_deallocate_a(kweight)
1487 safe_deallocate_a(reduced)
1496 type(lattice_vectors_t),
intent(in) :: latt
1498 integer :: ig1, ig2, ik
1499 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1500 real(real64) :: vec(grid%dim), kpt(grid%dim)
1501 real(real64) :: d, dmin
1506 do ig1 = 1, grid%dim
1507 do ig2 = 1, 3**grid%dim
1508 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1512 do ig1 = 1, 3**grid%dim
1516 do ik = 1, grid%npoints
1519 do ig1 = 1, 3**grid%dim
1520 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1521 d = real(sum(vec**2), real32)
1528 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1539 integer,
optional,
intent(in) :: iunit
1540 type(namespace_t),
optional,
intent(in) :: namespace
1541 logical,
optional,
intent(in) :: absolute_coordinates
1544 character(len=100) :: str_tmp
1549 call messages_print_with_emphasis(
'Brillouin zone sampling', iunit, namespace)
1553 call messages_write(
'Dimensions of the k-point grid =')
1554 do idir = 1, this%full%dim
1555 call messages_write(this%nik_axis(idir), fmt =
'(i3,1x)')
1557 call messages_new_line()
1559 if (.not. all(this%downsampling(1:this%full%dim) == 1))
then
1560 call messages_write(
'Dimensions of the q-point grid =')
1561 do idir = 1, this%full%dim
1562 call messages_write(this%niq_axis(idir), fmt =
'(i3,1x)')
1564 call messages_new_line()
1567 call messages_write(
'Total number of k-points =')
1568 call messages_write(this%full%npoints)
1569 call messages_new_line()
1571 call messages_write(
'Number of symmetry-reduced k-points =')
1572 call messages_write(this%reduced%npoints)
1574 call messages_info(iunit=iunit, namespace=namespace)
1578 call messages_write(
'Total number of k-points =')
1579 call messages_write(this%full%npoints)
1580 call messages_new_line()
1581 call messages_info(iunit=iunit, namespace=namespace)
1585 call messages_new_line()
1586 call messages_write(
'List of k-points:')
1587 call messages_info(iunit=iunit, namespace=namespace)
1589 write(message(1),
'(6x,a)')
'ik'
1590 do idir = 1, this%full%dim
1591 index = index2axis(idir)
1592 write(str_tmp,
'(9x,2a)')
'k_', index
1593 message(1) = trim(message(1)) // trim(str_tmp)
1595 write(str_tmp,
'(6x,a)')
'Weight'
1596 message(1) = trim(message(1)) // trim(str_tmp)
1597 message(2) =
'---------------------------------------------------------'
1598 call messages_info(2, iunit)
1601 write(message(1),
'(i8,1x)') ik
1602 do idir = 1, this%full%dim
1603 if (optional_default(absolute_coordinates, .false.))
then
1604 write(str_tmp,
'(f12.4)') this%reduced%point(idir, ik)
1606 write(str_tmp,
'(f12.4)') this%reduced%red_point(idir, ik)
1608 message(1) = trim(message(1)) // trim(str_tmp)
1611 message(1) = trim(message(1)) // trim(str_tmp)
1612 call messages_info(1, iunit, namespace=namespace)
1615 call messages_info(iunit=iunit, namespace=namespace)
1617 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1626 integer,
intent(in) :: ik
1634 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1636 integer,
intent(in) :: ik
1638 if (this%use_symmetries)
then
1639 num = this%num_symmetry_ops(ik)
1647 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1649 integer,
intent(in) :: ik
1650 integer,
intent(in) :: index
1652 if (this%use_symmetries)
then
1653 iop = this%symmetry_ops(ik, index)
1670 integer pure function kpoints_get_full_symmetry_op_index(this, ifull) result(iiop)
1672 integer,
intent(in) :: ifull
1674 if (this%use_symmetries)
then
1675 iiop = this%map_full_to_symidx(ifull)
1683 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1685 integer,
intent(in) :: ik
1686 integer,
intent(in) :: index
1691 if (this%use_symmetries)
then
1692 do iop = 1, this%num_symmetry_ops(ik)
1693 if (this%symmetry_ops(ik, iop) == index)
then
1709 integer :: denom, nik, nik_skip
1713 nik = this%full%npoints
1714 nik_skip = this%nik_skip
1721 do denom = 1, 100000
1722 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1723 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon))
then
1737 if (this%nik_skip > 0)
then
1740 have_zerow = .false.
1755 integer,
intent(in) :: ind
1757 coord = this%coord_along_path(ind)
1765 type(symmetries_t),
intent(in) :: symm
1766 integer,
intent(in) :: dim
1767 logical,
intent(in) :: time_reversal
1768 type(namespace_t),
intent(in) :: namespace
1770 integer,
allocatable :: kmap(:)
1771 real(real64) :: kpt(dim), diff(dim)
1772 integer :: nk, ik, ik2, iop
1773 type(distributed_t) :: kpt_dist
1780 call distributed_nullify(kpt_dist, nk)
1782 if (mpi_world%comm /= mpi_comm_undefined)
then
1783 call distributed_init(kpt_dist, nk, mpi_comm_world,
"kpt_check")
1788 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1790 do iop = 1, symmetries_number(symm)
1791 if (iop == symmetries_identity_index(symm) .and. &
1792 .not. time_reversal) cycle
1794 do ik = kpt_dist%start, kpt_dist%end
1798 do ik = kpt_dist%start, kpt_dist%end
1800 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1802 kpt = kpt - anint(kpt + m_half*symprec)
1807 if (iop /= symmetries_identity_index(symm))
then
1808 diff = kpt - grid%red_point(:, ik2)
1809 diff = diff - anint(diff)
1811 if (sum(abs(diff)) < symprec)
then
1817 if (time_reversal)
then
1818 diff = kpt + grid%red_point(:, ik2)
1819 diff = diff - anint(diff)
1821 if (sum(abs(diff)) < symprec)
then
1829 if (kmap(ik) == ik)
then
1830 write(message(1),
'(a,i5,a2,3(f7.3,a2),a)')
"The reduced k-point ", ik,
" (", &
1831 grid%red_point(1, ik),
", ", grid%red_point(2, ik),
", ", grid%red_point(3, ik), &
1832 ") ",
"has no symmetric in the k-point grid for the following symmetry"
1833 write(message(2),
'(i5,1x,a,2x,3(3i4,2x))') iop,
':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1834 message(3) =
"Change your k-point grid or use KPointsUseSymmetries=no."
1835 call messages_fatal(3, namespace=namespace)
1840 safe_deallocate_a(kmap)
1842 call distributed_end(kpt_dist)
1850 integer,
intent(in) :: ik
1851 integer,
intent(in) :: iq
1853 integer :: dim, idim
1854 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1859 dim = kpt%reduced%dim
1862 if (all(kpt%downsampling == 1))
then
1869 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1872 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1873 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1874 if (abs(red(idim) - anint(red(idim))) > m_epsilon)
then
1875 compatible = .false.
1889 if (
allocated(this%coord_along_path))
then
1890 npath =
SIZE(this%coord_along_path)
1909 type(lattice_vectors_t),
intent(in) :: new_latt
1915 this%latt = new_latt
1917 do ik = 1, this%reduced%npoints
1918 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1921 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.