Octopus
kpoints.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module kpoints_oct_m
22 use debug_oct_m
24 use global_oct_m
25 use, intrinsic :: iso_fortran_env
28 use mpi_oct_m
30 use parser_oct_m
32 use simplex_oct_m, only: simplex_t
33 use sort_oct_m
36 use unit_oct_m
38 use utils_oct_m
39
40 implicit none
41
42 private
43
44 public :: &
46 kpoints_t, &
73
75 ! Components are public by default
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
84 integer :: dim = 0
85 end type kpoints_grid_t
86
87 type kpoints_t
88 ! Components are public by default
89
90 type(lattice_vectors_t) :: latt
91
92 type(kpoints_grid_t) :: full
93 type(kpoints_grid_t) :: reduced
94
95 integer :: method = 0
96
97 logical :: use_symmetries = .false.
98 logical :: use_time_reversal = .false.
99 integer :: nik_skip = 0
100
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(:)
111
113 real(real64), allocatable, private :: coord_along_path(:)
114
115 integer, allocatable :: downsampling(:)
117 type(symmetries_t), pointer :: symm => null()
118
119 contains
120 procedure :: have_zero_weight_path => kpoints_have_zero_weight_path
121 procedure :: get_kpoint_method => kpoints_get_kpoint_method
122 procedure :: gamma_only => kpoints_gamma_only
123 procedure :: get_weight => kpoints_get_weight
124 procedure :: get_equiv => kpoints_get_equiv
125 procedure :: get_full_symmetry_op_index => kpoints_get_full_symmetry_op_index
126 procedure :: get_point => kpoints_get_point
127 procedure :: write_info => kpoints_write_info
128 procedure :: nkpt_in_path => kpoints_nkpt_in_path
129 end type kpoints_t
130
131 integer, public, parameter :: &
132 KPOINTS_GAMMA = 2, &
133 kpoints_monkh_pack = 4, &
134 kpoints_user = 8, &
135 kpoints_path = 16
136
137contains
138
139 ! ---------------------------------------------------------
140 subroutine kpoints_grid_init(dim, this, npoints, nshifts)
141 integer, intent(in) :: dim
142 type(kpoints_grid_t), intent(out) :: this
143 integer, intent(in) :: npoints
144 integer, intent(in) :: nshifts
145
146 push_sub(kpoints_grid_init)
147
148 this%dim = dim
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))
156
157 pop_sub(kpoints_grid_init)
158 end subroutine kpoints_grid_init
159
160 ! ---------------------------------------------------------
161 subroutine kpoints_grid_end(this)
162 type(kpoints_grid_t), intent(inout) :: this
163
164 push_sub(kpoints_grid_end)
165
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)
174 end subroutine kpoints_grid_end
176 ! ---------------------------------------------------------
177 subroutine kpoints_grid_copy(bb, aa)
178 type(kpoints_grid_t), intent(in) :: bb
179 type(kpoints_grid_t), intent(inout) :: aa
180
181 push_sub(kpoints_grid_copy)
183 call kpoints_grid_end(aa)
184 call kpoints_grid_init(bb%dim, aa, bb%npoints, bb%nshifts)
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)
191 pop_sub(kpoints_grid_copy)
192 end subroutine kpoints_grid_copy
194 ! ---------------------------------------------------------
195 subroutine kpoints_grid_addto(this, that)
196 type(kpoints_grid_t), intent(inout) :: this
197 type(kpoints_grid_t), intent(in) :: that
199 type(kpoints_grid_t) :: old_grid
200
201 push_sub(kpoints_grid_addto)
203 if (.not. allocated(that%point)) then
205 return
206 end if
207
208 if (.not. allocated(this%point)) then
209 call kpoints_grid_copy(that, this)
211 return
212 end if
213
214 call kpoints_grid_copy(this, old_grid)
217 call kpoints_grid_init(old_grid%dim, this, that%npoints + old_grid%npoints, old_grid%nshifts)
219 this%red_point = m_zero
220 this%point = m_zero
221 this%weight = m_zero
222 this%shifts = m_zero
224 ! Fill the the result with values form this
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)
230
231 ! Fill the result with that
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)
236
237 call kpoints_grid_end(old_grid)
238
239
240 pop_sub(kpoints_grid_addto)
241 end subroutine kpoints_grid_addto
242
243
245 function kpoints_set_method(namespace, use_symmetries, only_gamma) result(method)
246 type(namespace_t), intent(in) :: namespace
247 logical, intent(in) :: use_symmetries
248 logical, intent(in) :: only_gamma
249
250 integer :: method
251
252 push_sub(kpoints_set_method)
253
254 method = 0
255
256 if (only_gamma) then
257 method = kpoints_gamma
258 pop_sub(kpoints_set_method)
259 return
260 end if
261
262 !Monkhorst Pack grid
263 if (parse_is_defined(namespace, 'KPointsGrid')) then
264 method = ior(method, kpoints_monkh_pack)
265 end if
266
267 !User-defined kpoints
268 if (parse_is_defined(namespace, 'KPointsReduced').or. parse_is_defined(namespace, 'KPoints')) then
269 method = ior(method, kpoints_user)
270 if (use_symmetries) then
271 write(message(1), '(a)') "User-defined k-points are not compatible with KPointsUseSymmetries=yes."
272 call messages_warning(1, namespace=namespace)
273 end if
274 end if
275
276 !User-defined k-points path
277 if (parse_is_defined(namespace, 'KPointsPath')) then
278 method = ior(method, kpoints_path)
279 if (use_symmetries) then
280 write(message(1), '(a)') "KPointsPath is not compatible with KPointsUseSymmetries=yes."
281 call messages_warning(1, namespace=namespace)
282 end if
283 end if
284
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."
288 call messages_warning(2, namespace=namespace)
289 method = kpoints_monkh_pack
290 end if
291
292 pop_sub(kpoints_set_method)
293
294 end function kpoints_set_method
295
297 subroutine kpoints_allocate_and_init(this, symm, dim, latt)
298 type(kpoints_t), intent(inout) :: this
299 type(symmetries_t), target, intent(in) :: symm
300 integer, intent(in) :: dim
301 type(lattice_vectors_t), intent(in) :: latt
302
304
305 this%latt = latt
306 this%symm => symm
307
308 safe_allocate(this%nik_axis(1:dim))
309 safe_allocate(this%niq_axis(1:dim))
310 safe_allocate(this%downsampling(1:dim))
311
312 this%nik_axis = 1
313 this%niq_axis = 1
314 this%downsampling = 1
315 this%nik_skip = 0
316 safe_deallocate_a(this%map_full_to_reduced)
317 safe_deallocate_a(this%map_full_to_symidx)
318
320 end subroutine kpoints_allocate_and_init
321
322 ! ---------------------------------------------------------
323 subroutine kpoints_init(this, namespace, symm, dim, periodic_dim, latt, grp)
324 type(kpoints_t), intent(out) :: this
325 type(namespace_t), intent(in) :: namespace
326 type(symmetries_t), target, intent(in) :: symm
327 integer, intent(in) :: dim
328 integer, intent(in) :: periodic_dim
329 type(lattice_vectors_t), intent(in) :: latt
330 type(mpi_grp_t), intent(in) :: grp
331
332 logical :: only_gamma, default_timereversal
333
334 push_sub(kpoints_init)
335
336 !%Variable KPointsUseSymmetries
337 !%Type logical
338 !%Default no
339 !%Section Mesh::KPoints
340 !%Description
341 !% This variable defines whether symmetries are taken into account
342 !% or not for the choice of <i>k</i>-points. If it is set to no, the <i>k</i>-point
343 !% sampling will range over the full Brillouin zone.
344 !%
345 !% When a perturbation is applied to the system, the full
346 !% symmetries of the system cannot be used. In this case you must
347 !% not use symmetries or use the <tt>SymmetryBreakDir</tt> to tell
348 !% Octopus the direction of the perturbation (for the moment this
349 !% has to be done by hand by the user, in the future it will be
350 !% automatic).
351 !%
352 !%End
353 call parse_variable(namespace, 'KPointsUseSymmetries', .false., this%use_symmetries)
354
355 !%Variable KPointsUseTimeReversal
356 !%Type logical
357 !%Section Mesh::KPoints
358 !%Description
359 !% If symmetries are used to reduce the number of <i>k</i>-points,
360 !% this variable defines whether time-reversal symmetry is taken
361 !% into account or not. If it is set to no, the <i>k</i>-point
362 !% sampling will not be reduced according to time-reversal
363 !% symmetry.
364 !%
365 !% The default is yes, unless symmetries are broken in one
366 !% direction by the <tt>SymmetryBreakDir</tt> block.
367 !%
368 !% Warning: For time propagation runs with an external field,
369 !% time-reversal symmetry should not be used.
370 !%
371 !%End
372 default_timereversal = this%use_symmetries .and. .not. symmetries_have_break_dir(symm)
373 call parse_variable(namespace, 'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
374
375 only_gamma = (periodic_dim == 0)
376 this%method = kpoints_set_method(namespace, this%use_symmetries, only_gamma)
377 call kpoints_allocate_and_init(this, symm, dim, latt)
378
379 if (only_gamma) then
380 call kpoints_read_mp(this, namespace, symm, dim, grp, gamma_only=.true.)
381 pop_sub(kpoints_init)
382 return
383 end if
384
385 if (bitand(this%method, kpoints_monkh_pack) /= 0) then
386 call kpoints_read_mp(this, namespace, symm, dim, grp, gamma_only=.false.)
387 end if
388
389 if (bitand(this%method, kpoints_user) /= 0) then
390 call kpoints_read_user_kpoints(this, namespace, dim)
391 end if
393 if (bitand(this%method, kpoints_path) /= 0) then
394 call kpoints_read_path(this, namespace, dim)
395 end if
396
397 call kpoints_print_info(this, namespace)
398
399 pop_sub(kpoints_init)
400 end subroutine kpoints_init
401
403 subroutine kpoints_read_mp(this, namespace, symm, dim, grp, gamma_only)
404 type(kpoints_t), intent(inout) :: this
405 type(namespace_t), intent(in) :: namespace
406 type(symmetries_t), intent(in) :: symm
407 integer, intent(in) :: dim
408 type(mpi_grp_t), intent(in) :: grp
409 logical, intent(in) :: gamma_only
410
411 logical :: gamma_only_
412 integer :: ii, ik, is, ncols, nshifts
413 type(block_t) :: blk
414 integer, allocatable :: symm_ops(:, :), num_symm_ops(:)
415 real(real64), allocatable :: shifts(:, :)
416
417 push_sub(kpoints_read_mp)
419 call messages_obsolete_variable(namespace, 'KPointsMonkhorstPack', 'KPointsGrid')
420
421 !%Variable KPointsGrid
422 !%Type block
423 !%Default <math>\Gamma</math>-point only
424 !%Section Mesh::KPoints
425 !%Description
426 !% When this block is given (and the <tt>KPoints</tt> block is not present),
427 !% <i>k</i>-points are distributed in a uniform grid, according to a modified
428 !% version of the Monkhorst-Pack scheme. For the original MP scheme, see
429 !% James D. Pack and Hendrik J. Monkhorst,
430 !% <i>Phys. Rev. B</i> <b>13</b>, 5188 (1976) and <i>Phys. Rev. B</i> <b>16</b>, 1748 (1977).
431 !%
432 !% The number of columns should be equal to <tt>Dimensions</tt>,
433 !% but the grid and shift numbers should be 1 and zero in finite directions.
434 !%
435 !% The first row of the block is a set of integers defining
436 !% the number of <i>k</i>-points to be used along each direction
437 !% in reciprocal space. The numbers refer to the whole Brillouin
438 !% zone, and the actual number of <i>k</i>-points is usually
439 !% reduced exploiting the symmetries of the system. By default
440 !% the grid will always include the <math>\Gamma</math>-point.
441 !%
442 !% Optional rows can be added to specify multiple shifts in the <i>k</i>-points (between 0.0 and 1.0),
443 !% in units of the Brillouin zone divided by the number in the first row.
444 !% Please note that without specifying any shift, an implicit shift of -0.5 is added for odd number
445 !% of k-points, such that the Gamma point is always included.
446 !%
447 !% For example, the following input samples the BZ with 100 points in the
448 !% <i>xy</i>-plane of reciprocal space:
449 !%
450 !% <tt>%KPointsGrid
451 !% <br>&nbsp;&nbsp;10 | 10 | 1
452 !% <br>%</tt>
453 !%
454 !% is equivalent to
455 !%
456 !% <tt>%KPointsGrid
457 !% <br> 10 | 10 | 1
458 !% <br> 0 | 0 | -0.5
459 !% <br>%</tt>
460 !%
461 !%End
462
463 gamma_only_ = gamma_only
464 if (.not. gamma_only_) then
465 gamma_only_ = (parse_block(namespace, 'KPointsGrid', blk) /= 0)
466 end if
467
468 this%nik_axis = 1
469
470 if (.not. gamma_only_) then
471 nshifts = max(parse_block_n(blk)-1,1)
472 else
473 nshifts = 1
474 end if
475 safe_allocate(shifts(1:dim,1:nshifts))
476 shifts = m_zero
477
478 if (.not. gamma_only_) then
479 ncols = parse_block_cols(blk, 0)
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
483 call messages_fatal(1, namespace=namespace)
484 else
485 write(message(2),'(a)') 'Continuing, but ignoring the additional values.'
486 call messages_warning(2, namespace=namespace)
487 end if
488 end if
489 do ii = 1, dim
490 call parse_block_integer(blk, 0, ii - 1, this%nik_axis(ii))
491 end do
492
493 if (any(this%nik_axis < 1)) then
494 message(1) = 'Input: KPointsGrid is not valid.'
495 call messages_fatal(1, namespace=namespace)
496 end if
497
498 if (parse_block_n(blk) > 1) then ! we have a shift, or even more
499 ncols = parse_block_cols(blk, 1)
500 if (ncols /= dim) then
501 write(message(1),'(a,i3,a,i3)') 'KPointsGrid shift has ', ncols, ' columns but must have ', dim
502 call messages_fatal(1, namespace=namespace)
503 end if
504 do is = 1, nshifts
505 do ii = 1, dim
506 call parse_block_float(blk, is, ii - 1, shifts(ii,is))
507 end do
508 end do
509 else
510 !We include a default 0.5 shift for odd number of k-points
511 do ii = 1, dim
512 if (mod(this%nik_axis(ii), 2) /= 0) then
513 shifts(ii,1) = m_half
514 end if
515 end do
516 end if
517
518 call parse_block_end(blk)
519 else
520 shifts(:, 1) = -m_half
521 end if
522
523 !%Variable QPointsGrid
524 !%Type block
525 !%Default KPointsGrid
526 !%Section Mesh::KPoints
527 !%Description
528 !% This block allows to define a q-point grid used for the calculation of the Fock operator
529 !% with k-points. The <i>q</i>-points are distributed in a uniform grid, as done for the
530 !% <tt>KPointsGrid</tt> variable.
531 !% See J. Chem Phys. 124, 154709 (2006) for details
532 !%
533 !% For each dimension, the number of q point must be a divider of the number of k point
534 !%
535 !% <tt>%QPointsGrid
536 !% <br>&nbsp;&nbsp;2 | 2 | 1
537 !% <br>%</tt>
538 !%
539 !% At the moment, this is not compatible with k-point symmetries.
540 !%
541 !%End
542 this%niq_axis(:) = this%nik_axis(:)
543 this%downsampling(:) = 1
544 if (parse_is_defined(namespace, 'QPointsGrid')) then
545 if (parse_block(namespace, 'QPointsGrid', blk) == 0) then
546 ncols = parse_block_cols(blk, 0)
547 if (ncols /= dim) then
548 write(message(1),'(a,i3,a,i3)') 'QPointsGrid first row has ', ncols, ' columns but must have ', dim
549 call messages_fatal(1, namespace=namespace)
550 end if
551 do ii = 1, dim
552 call parse_block_integer(blk, 0, ii - 1, this%niq_axis(ii))
553 end do
554
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.'
557 call messages_fatal(1, namespace=namespace)
558 end if
559
560 this%downsampling = this%nik_axis/this%niq_axis
561
562 if (any(this%downsampling /= 1) .and. this%use_symmetries) then
563 call messages_not_implemented('QPointsGrid together with k-point symmetries', namespace=namespace)
564 end if
565
566 call parse_block_end(blk)
567 end if
568 end if
569
570 call kpoints_grid_init(dim, this%full, product(this%nik_axis)*nshifts, nshifts)
571
572 !We move the k-points into this%shifts
573 this%full%shifts(:, :) = shifts(:, :)
574 safe_deallocate_a(shifts)
575
576 ! The grid labels are kept, as they give the position of a k-point on the
577 ! Monkhorst-Pack grid without having to recover it from its coordinates.
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, &
580 lk123 = this%lk123)
581
582 do ik = 1, this%full%npoints
583 call kpoints_to_absolute(this%latt, this%full%red_point(:, ik), this%full%point(:, ik))
584 end do
585
586 this%full%weight = m_one / this%full%npoints
587
588 if (this%use_symmetries) then
589 message(1) = "Checking if the generated full k-point grid is symmetric"
590 call messages_info(1, namespace=namespace)
591 call kpoints_check_symmetries(this%full, symm, dim, this%use_time_reversal, grp, namespace)
592 end if
593
594 call kpoints_grid_copy(this%full, this%reduced)
595
596 if (this%use_symmetries) then
597 safe_allocate(num_symm_ops(1:this%full%npoints))
598
599 if (this%use_time_reversal) then
600 safe_allocate(symm_ops(1:this%full%npoints, 1:2*symmetries_number(symm)))
601 else
602 safe_allocate(symm_ops(1:this%full%npoints, 1:symmetries_number(symm)))
603 end if
604
605 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
606 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
607 call kpoints_grid_reduce(symm, this%use_time_reversal, &
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)
610
611 assert(maxval(num_symm_ops) >= 1)
612 if (this%use_time_reversal) then
613 assert(maxval(num_symm_ops) <= 2*symmetries_number(symm))
614 else
615 assert(maxval(num_symm_ops) <= symmetries_number(symm))
616 end if
617
618 ! the total number of symmetry operations in the list has to be equal to the number of k-points
619 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
620
621 do ik = 1, this%reduced%npoints
622 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
623 end do
624
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))
627
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))
631
632 safe_deallocate_a(num_symm_ops)
633 safe_deallocate_a(symm_ops)
634 else
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
642 end do
643 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
644 this%map_full_to_symidx(:) = 1
645 end if
646
647 do ik = 1, this%reduced%npoints
648 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
649 end do
650
651 call kpoints_fold_to_1bz(this%full, this%latt)
652 call kpoints_fold_to_1bz(this%reduced, this%latt)
653
654 block
655 integer(int64) :: dos_method, smearing_function
656 logical :: use_simplex, use_simplex_opt
657
658 call parse_variable(namespace, 'DOSMethod', option__dosmethod__smear, dos_method)
659 call parse_variable(namespace, 'SmearingFunction', option__smearingfunction__semiconducting, smearing_function)
660
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
665
666 if (use_simplex .and. use_simplex_opt) then
667 call messages_not_implemented("DOSMethod and SmearingFunction with different tetrahedron methods", namespace=namespace)
668 end if
669
670 if (use_simplex .or. use_simplex_opt) then
671 safe_deallocate_p(this%full%simplex)
672 safe_deallocate_p(this%reduced%simplex)
673 end if
674
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, &
677 opt = .false.)
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, &
682 opt = .true.)
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.)
685 end if
686 end block
687
688 pop_sub(kpoints_read_mp)
689 end subroutine kpoints_read_mp
690
691
693 subroutine kpoints_read_path(this, namespace, dim)
694 type(kpoints_t), intent(inout) :: this
695 type(namespace_t), intent(in) :: namespace
696 integer, intent(in) :: dim
697
698 type(block_t) :: blk
699 integer :: nshifts, nkpoints, nhighsympoints, nsegments
700 integer :: icol, ik, idir, ncols, npoints
701 integer, allocatable :: resolution(:)
702 real(real64), allocatable :: highsympoints(:, :)
703 type(kpoints_grid_t) :: path_kpoints_grid
704 integer, allocatable :: symm_ops(:, :), num_symm_ops(:)
705
706 push_sub(kpoints_read_path)
707
708 !%Variable KPointsPath
709 !%Type block
710 !%Section Mesh::KPoints
711 !%Description
712 !% When this block is given, <i>k</i>-points are generated along a path
713 !% defined by the points of the list.
714 !% The points must be given in reduced coordinates.
715 !%
716 !% The first row of the block is a set of integers defining
717 !% the number of <i>k</i>-points for each segments of the path.
718 !% The number of columns should be equal to <tt>Dimensions</tt>,
719 !% and the k-points coordinate should be zero in finite directions.
720 !%
721 !% For example, the following input samples the BZ with 15 points:
722 !%
723 !% <tt>%KPointsPath
724 !% <br>&nbsp;&nbsp;10 | 5
725 !% <br>&nbsp;&nbsp; 0 | 0 | 0
726 !% <br>&nbsp;&nbsp; 0.5 | 0 | 0
727 !% <br>&nbsp;&nbsp; 0.5 | 0.5 | 0.5
728 !% <br>%</tt>
729 !%
730 !%End
731
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)
735 end if
736
737 ! There is one high symmetry k-point per line
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)
743 end if
744
745 safe_allocate(resolution(1:nsegments))
746 do icol = 1, nsegments
747 call parse_block_integer(blk, 0, icol-1, resolution(icol))
748 end do
749 !Total number of points in the segment
750 nkpoints = sum(resolution) + 1
751
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)
758 end if
759
760 do idir = 1, dim
761 call parse_block_float(blk, ik, idir-1, highsympoints(idir, ik))
762 end do
763 end do
764
765 call parse_block_end(blk)
766
767 !We do not have shifts
768 nshifts = 1
769 call kpoints_grid_init(dim, path_kpoints_grid, nkpoints, nshifts)
770
771 ! For the output of band-structures
772 safe_allocate(this%coord_along_path(1:nkpoints))
773
774 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
775 this%coord_along_path)
776
777 safe_deallocate_a(resolution)
778 safe_deallocate_a(highsympoints)
779
780 !Use zero weight for the path so that it can be used with any kind of calculation mode
781 !without interfering with the physical BZ integral.
782 if (this%method == kpoints_path) then
783 path_kpoints_grid%weight = m_one/path_kpoints_grid%npoints
784 else
785 path_kpoints_grid%weight = m_zero
786 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
787 end if
789 !The points have been generated in absolute coordinates
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))
792 end do
793
794 call kpoints_fold_to_1bz(path_kpoints_grid, this%latt)
795
796 !We need to copy the arrays containing the information on the symmetries
797 !Before calling kpoints_grid_addto
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)))
802
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))
806 end if
807
808 call kpoints_grid_addto(this%full , path_kpoints_grid)
809 call kpoints_grid_addto(this%reduced, path_kpoints_grid)
810
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)))
816
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
822
823 safe_deallocate_a(num_symm_ops)
824 safe_deallocate_a(symm_ops)
825 else if(this%use_symmetries) then ! If symmetries are activated but no KPointsGrid specified
826 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
827 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
828
829 this%num_symmetry_ops(1:this%reduced%npoints) = 1
830 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
831 end if
832
833 call kpoints_grid_end(path_kpoints_grid)
834
835 pop_sub(kpoints_read_path)
836 end subroutine kpoints_read_path
837
838
840 subroutine kpoints_read_user_kpoints(this, namespace, dim)
841 type(kpoints_t), intent(inout) :: this
842 type(namespace_t), intent(in) :: namespace
843 integer, intent(in) :: dim
844
845 type(block_t) :: blk
846 logical :: reduced
847 integer :: ik, idir
848 real(real64) :: weight_sum
849 type(kpoints_grid_t) :: user_kpoints_grid
850
852
853 !%Variable KPoints
854 !%Type block
855 !%Section Mesh::KPoints
856 !%Description
857 !% This block defines an explicit set of <i>k</i>-points and their weights for
858 !% a periodic-system calculation. The first column is the weight
859 !% of each <i>k</i>-point and the following are the components of the <i>k</i>-point
860 !% vector. You only need to specify the components for the
861 !% periodic directions. Note that the <i>k</i>-points should be given in
862 !% Cartesian coordinates (not in reduced coordinates), in the units of inverse length.
863 !% The weights will be renormalized so they sum to 1 (and must be rational numbers).
864 !%
865 !% For example, if you want to include only the Gamma point, you can
866 !% use:
867 !%
868 !% <tt>%KPoints
869 !% <br>&nbsp;&nbsp;1.0 | 0 | 0 | 0
870 !% <br>%</tt>
871 !%
872 !%End
873
874 !%Variable KPointsReduced
875 !%Type block
876 !%Section Mesh::KPoints
877 !%Description
878 !% Same as the block <tt>KPoints</tt> but this time the input is given in reduced
879 !% coordinates, <i>i.e.</i>
880 !% what <tt>Octopus</tt> writes in a line in the ground-state standard output as
881 !%
882 !% <tt>#k = 1, k = ( 0.154000, 0.154000, 0.154000)</tt>.
883 !%End
884
885 reduced = .false.
886 if (parse_block(namespace, 'KPoints', blk) /= 0) then
887 if (parse_block(namespace, 'KPointsReduced', blk) == 0) then
888 reduced = .true.
889 else
890 ! This case should really never happen
891 write(message(1),'(a)') 'Internal error loading user-defined k-point list.'
892 call messages_fatal(1, namespace=namespace)
893 end if
894 end if
895
896 call kpoints_grid_init(dim, user_kpoints_grid, parse_block_n(blk), 1)
897
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
902
903 if (reduced) then
904 do ik = 1, user_kpoints_grid%npoints
905 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
906 do idir = 1, dim
907 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%red_point(idir, ik))
908 end do
909 ! generate also the absolute coordinates
910 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
911 end do
912 else
913 do ik = 1, user_kpoints_grid%npoints
914 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
915 do idir = 1, dim
916 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%point(idir, ik), unit_one/units_inp%length)
917 end do
918 ! generate also the reduced coordinates
919 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
920 end do
921 end if
922 call parse_block_end(blk)
923
924 this%nik_skip = 0
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)
929 ! count k-points with zero weight and make sure the points are given in
930 ! a block after all regular k-points. This is for convenience, so they can be skipped
931 ! easily and not a big restraint for the user who has to provide the k-points
932 ! explicitly anyway.
933 do ik=1,user_kpoints_grid%npoints
934 if (user_kpoints_grid%weight(ik) < m_epsilon) then
935 ! check there are no points with positive weight following a zero weighted one
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)
940 end if
941 end if
942 this%nik_skip = this%nik_skip + 1
943 user_kpoints_grid%weight(ik) = m_zero
944 end if
945 end do
946 end if
947 ! renormalize weights
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)
952 end if
953 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
954
955 ! for the moment we do not apply symmetries to user kpoints
956 ! call kpoints_grid_copy(this%full, this%reduced)
957
958 call kpoints_fold_to_1bz(user_kpoints_grid, this%latt)
959
960 call kpoints_grid_addto(this%full , user_kpoints_grid)
961 call kpoints_grid_addto(this%reduced, user_kpoints_grid)
962
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)
965
966 call kpoints_grid_end(user_kpoints_grid)
967
969 end subroutine kpoints_read_user_kpoints
970
971 ! ---------------------------------------------------------
972 subroutine kpoints_end(this)
973 type(kpoints_t), intent(inout) :: this
974
975 push_sub(kpoints_end)
976
977 call kpoints_grid_end(this%full)
978 call kpoints_grid_end(this%reduced)
979
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)
989
990 pop_sub(kpoints_end)
991 end subroutine kpoints_end
992
993
994 subroutine kpoints_print_info(this, namespace)
995 type(kpoints_t), intent(in) :: this
996 type(namespace_t), intent(in) :: namespace
997
998 integer :: idir, is, ik, dim
999 character(len=100) :: str_tmp
1000
1001 push_sub(kpoints_print_info)
1002
1003 dim = this%reduced%dim
1004
1005 if (bitand(this%method, kpoints_monkh_pack) /= 0) then
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 ='
1010 do idir = 1, dim
1011 write(str_tmp,'(i5)') this%nik_axis(idir)
1012 message(4) = trim(message(4)) // trim(str_tmp)
1013 end do
1014 call messages_info(4, namespace=namespace)
1015
1016 do is = 1, this%reduced%nshifts
1017 write(message(1),'(a)') ' '
1018 write(message(2),'(4x,a,i1,a)') 's', is, ' ='
1019 do idir = 1, dim
1020 write(str_tmp,'(f6.2)') this%reduced%shifts(idir,is)
1021 message(2) = trim(message(2)) // trim(str_tmp)
1022 end do
1023 call messages_info(2, namespace=namespace)
1024 end do
1025 end if
1026
1027 write(message(1),'(a)') ' '
1028 write(message(2),'(a)') ' index | weight | coordinates |'
1029 call messages_info(2, namespace=namespace)
1030
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
1034 do idir = 1, dim
1035 write(str_tmp,'(f12.6)') this%reduced%red_point(idir, ik)
1036 message(1) = trim(message(1)) // trim(str_tmp)
1037 end do
1038 write(str_tmp,'(a)') " |"
1039 message(1) = trim(message(1)) // trim(str_tmp)
1040 call messages_info(1, namespace=namespace)
1041 end do
1042
1043 write(message(1),'(a)') ' '
1044 call messages_info(1, namespace=namespace)
1045
1046 pop_sub(kpoints_print_info)
1047
1048 end subroutine kpoints_print_info
1049
1050 ! ---------------------------------------------------------
1051 subroutine kpoints_to_absolute(latt, kin, kout)
1052 type(lattice_vectors_t), intent(in) :: latt
1053 real(real64), intent(in) :: kin(:)
1054 real(real64), contiguous, intent(out) :: kout(:)
1055
1056 push_sub(kpoints_to_absolute)
1057
1058 kout = matmul(latt%klattice, kin)
1059
1060 pop_sub(kpoints_to_absolute)
1061 end subroutine kpoints_to_absolute
1062
1063 ! ---------------------------------------------------------
1064 subroutine kpoints_to_reduced(latt, kin, kout)
1065 type(lattice_vectors_t), intent(in) :: latt
1066 real(real64), contiguous, intent(in) :: kin(:)
1067 real(real64), contiguous, intent(out) :: kout(:)
1068
1069 push_sub(kpoints_to_reduced)
1070
1071 kout = matmul(kin, latt%rlattice) / (m_two*m_pi)
1072
1073 pop_sub(kpoints_to_reduced)
1074 end subroutine kpoints_to_reduced
1075
1076
1077 ! ---------------------------------------------------------
1078 subroutine kpoints_copy(kin, kout)
1079 type(kpoints_t), intent(in) :: kin
1080 type(kpoints_t), intent(inout) :: kout
1081
1082 push_sub(kpoints_copy)
1083
1084 call kpoints_end(kout)
1085
1086 kout%method = kin%method
1087
1088 call kpoints_grid_copy(kin%full, kout%full)
1089 call kpoints_grid_copy(kin%reduced, kout%reduced)
1090
1091 kout%use_symmetries = kin%use_symmetries
1092 kout%use_time_reversal = kin%use_time_reversal
1093
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(:)
1100
1101 if (allocated(kin%lk123)) then
1102 safe_allocate(kout%lk123(1:kin%full%npoints, 1:kin%full%dim))
1103 kout%lk123(:, :) = kin%lk123(:, :)
1104 end if
1105
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)
1109 end if
1110
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))
1117 end if
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)
1121 end if
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)
1125 end if
1126
1127 pop_sub(kpoints_copy)
1128 end subroutine kpoints_copy
1129
1130
1131 ! ----------------------------------------------------------
1132 integer pure function kpoints_number(this) result(number)
1133 type(kpoints_t), intent(in) :: this
1134
1135 number = this%reduced%npoints
1136
1137 end function kpoints_number
1138
1139
1140 ! ----------------------------------------------------------
1141 pure function kpoints_get_point(this, ik, absolute_coordinates) result(point)
1142 class(kpoints_t), intent(in) :: this
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)
1149 else
1150 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1151 end if
1152
1153 end function kpoints_get_point
1154
1155
1156 ! ----------------------------------------------------------
1157 real(real64) pure function kpoints_get_weight(this, ik) result(weight)
1158 class(kpoints_t), intent(in) :: this
1159 integer, intent(in) :: ik
1160
1161 weight = this%reduced%weight(ik)
1162
1163 end function kpoints_get_weight
1164
1165
1166 ! ----------------------------------------------------------
1175 integer function kpoints_get_equiv(this, ik) result(equiv)
1176 class(kpoints_t), intent(in) :: this
1177 integer, intent(in) :: ik
1178
1179 assert(allocated(this%map_full_to_reduced))
1180 equiv = this%map_full_to_reduced(ik)
1181
1182 end function kpoints_get_equiv
1183
1184
1185 ! ----------------------------------------------------------
1193 subroutine kpoints_grid_generate(dim, naxis, nshifts, shift, kpoints, lk123)
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(:, :)
1200 ! !< running from 0 to naxis(1:3).
1201
1202 real(real64) :: dx(dim)
1203 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1204 integer, allocatable :: lk123_(:, :), idx(:)
1205
1206 push_sub(kpoints_grid_generate)
1207
1208 dx = m_one/(m_two*naxis)
1209
1210 npoints = product(naxis)
1211
1212 safe_allocate(idx(1:npoints*nshifts))
1213 if (present(lk123)) then
1214 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1215 end if
1216
1217 do is = 1, nshifts
1218 do ii = 0, npoints - 1
1219 ik = npoints*is - ii
1220 jj = ii
1221 divisor = npoints
1222
1223 do idir = 1, dim
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)
1229 !A default shift of +0.5 is including in case if (mod(naxis(idir), 2) /= 0)
1230
1231 !bring back point to first Brillouin zone, except for points at 1/2
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
1234 end if
1235
1236 end do
1237 if (present(lk123)) then
1238 lk123_(ik, :) = ix
1239 idx(ik) = ik
1240 end if
1241 end do
1242 end do
1243
1244 call kpoints_deterministic_sort(naxis, kpoints, nshifts=nshifts, indices=idx)
1245
1246 if (present(lk123)) then
1247 do ik = 1, npoints*nshifts
1248 lk123(ik,:) = lk123_(idx(ik),:)
1249 end do
1250 safe_deallocate_a(lk123_)
1251 end if
1253 safe_deallocate_a(idx)
1254
1255 pop_sub(kpoints_grid_generate)
1256
1257 end subroutine kpoints_grid_generate
1258
1259
1267 subroutine kpoints_deterministic_sort(nik_axis, kpoints, nshifts, indices)
1268 integer, contiguous, intent(in ) :: nik_axis(:)
1269 real(real64), contiguous, intent(inout) :: kpoints(:, :)
1270 ! In: Unsorted
1271 ! Out: Sorted
1272 integer, optional, intent(in) :: nshifts
1273 integer, contiguous, optional, intent(out) :: indices(:)
1274 ! original column chosen for sorted position ik_sorted
1275
1276 integer :: ndim, nk, ik, nshifts_
1277 real(real64) :: dk(size(kpoints, 1))
1278 integer, allocatable :: idx(:)
1279 real(real64), allocatable :: shell(:), kpoints_unsorted(:, :)
1280
1282
1283 ndim = size(kpoints, 1)
1284 nshifts_ = optional_default(nshifts, 1)
1285 nk = product(nik_axis) * nshifts_
1286
1287 ! The MP generator is defined as k = (2*ix - N + 2*shift) * dk
1288 ! Therefore, for a single step where ix = 1,
1289 ! Delta k = 2 * dk, so to be consistent dk = 1 / 2N, such that Delta k = 1/N
1290 dk = m_one / (m_two * nik_axis)
1291
1292 safe_allocate(shell(1:nk))
1293 safe_allocate(idx(1:nk))
1294 safe_allocate_source(kpoints_unsorted(1:ndim, 1:nk), kpoints)
1295
1296 ! Squared length of the index-space coordinate
1297 do ik = 1, nk
1298 shell(ik) = sum((kpoints_unsorted(:, ik) / dk)**2)
1299 enddo
1300
1301 call robust_sort_by_abs(shell, kpoints_unsorted, idx)
1302 safe_deallocate_a(shell)
1303
1304 do ik = 1, nk
1305 kpoints(:, ik) = kpoints_unsorted(:, idx(ik))
1306 end do
1307
1308 if (present(indices)) indices = idx
1309
1310 safe_deallocate_a(idx)
1311 safe_deallocate_a(kpoints_unsorted)
1312
1314
1315 end subroutine kpoints_deterministic_sort
1316
1317
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)
1328
1329 integer :: is, ik, kpt_ind
1330 real(real64) :: length, total_length, accumulated_length
1331 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1332
1333 push_sub(kpoints_path_generate)
1334
1335 total_length = m_zero
1336 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1337 !We first compute the total length of the k-point path
1338 do is = 1, nsegments
1339 ! We need to work in abolute coordinates to get the correct path length
1340 call kpoints_to_absolute(latt, highsympoints(:,is), kpt1)
1341 call kpoints_to_absolute(latt, highsympoints(:,is+1), kpt2)
1342
1343 vec = kpt2 - kpt1
1344 length = norm2(vec)
1345 if (resolution(is) > 0) total_length = total_length + length
1346 end do
1347
1348 accumulated_length = m_zero
1349 kpt_ind = 0
1350 !Now we generate the points
1351 do is = 1, nsegments
1352 ! We need to work in abolute coordinates to get the correct path length
1353 call kpoints_to_absolute(latt, highsympoints(:, is), kpt1)
1354 call kpoints_to_absolute(latt, highsympoints(:, is+1), kpt2)
1355
1356 vec = kpt2 - kpt1
1357 length = norm2(vec)
1358 if (length > m_epsilon) vec = vec/length
1359
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
1364 end do
1365 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1366 end do
1367 !We add the last point
1368 kpt_ind = kpt_ind +1
1369 call kpoints_to_absolute(latt, highsympoints(:,nsegments+1), kpt1)
1370 coord(kpt_ind) = accumulated_length
1371 kpoints(:, kpt_ind) = kpt1
1372
1373 !The length of the total path is arbitrarily put to 1
1374 coord = coord/total_length
1375
1376 pop_sub(kpoints_path_generate)
1377 end subroutine kpoints_path_generate
1378
1379
1380 ! --------------------------------------------------------------------------------------------
1381 subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, &
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(:)
1393
1394 integer :: nreduced
1395 real(real64), allocatable :: reduced(:, :)
1396
1397 integer ik, iop, ik2
1398 real(real64) :: tran(dim), diff(dim)
1399 real(real64), allocatable :: kweight(:)
1400
1401 real(real64) :: prec
1402
1403 push_sub(kpoints_grid_reduce)
1404
1405 ! In case of really dense k-point grid, 1/nkpoints is might be smaller
1406 ! the symprec, causing problems
1407 ! Therefore we use PREC in the following
1408 prec = min(symprec, m_one/(nkpoints*100))
1409
1410 ! reduce to irreducible zone
1411
1412 ! kmap is used to mark reducible k-points and also to
1413 ! map reducible to irreducible k-points
1415 safe_allocate(kweight(1:nkpoints))
1416 safe_allocate(reduced(1:dim, 1:nkpoints))
1417
1418 kweight = m_one / nkpoints
1419
1420 nreduced = 0
1421 map_full_to_reduced(:) = -1 ! for safety
1422 map_full_to_symidx(:) = -1 ! for safety
1423
1424 num_symm_ops = 1
1425 symm_ops(:, 1) = symmetries_identity_index(symm)
1426
1427 do ik = 1, nkpoints
1428 if (kweight(ik) < prec) cycle
1429
1430 ! new irreducible point
1431 ! has reduced non-zero weight
1432 nreduced = nreduced + 1
1433 reduced(:, nreduced) = kpoints(:, ik)
1434 map_full_to_reduced(ik) = nreduced
1435 map_full_to_symidx(ik) = 1
1436
1437 !No need to check Gamma
1438 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1439
1440 if (ik == nkpoints) cycle
1441
1442 ! operate with the symmetry operations
1443 do iop = 1, symmetries_number(symm)
1444 if (iop == symmetries_identity_index(symm) .and. &
1445 .not. time_reversal) cycle ! no need to check for the identity
1446
1447 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1448 !We remove potential umklapp
1449 tran = tran - anint(tran + m_half*prec)
1450
1451 ! remove (mark) k-points related to irreducible reduced by symmetry
1452 do ik2 = ik + 1, nkpoints
1453 if (kweight(ik2) < prec) cycle
1454
1455 if (.not. iop == symmetries_identity_index(symm)) then ! no need to check for the identity
1456 diff = tran - kpoints(:, ik2)
1457 diff = diff - anint(diff)
1458
1459 ! both the transformed rk ...
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
1468 cycle
1469 end if
1470 end if
1471
1472 if (time_reversal) then
1473 diff = tran + kpoints(:, ik2)
1474 diff = diff - anint(diff)
1475
1476 ! and its inverse
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
1484 !We mark the symmetry+time-reversal operation as negative
1485 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1486 end if
1487 end if
1488 end do
1489 end do
1490 end do
1491
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)))
1495
1496 nkpoints = nreduced
1497 do ik = 1, nreduced
1498 kpoints(:, ik) = reduced(:, ik)
1499 end do
1500
1501 safe_deallocate_a(kweight)
1502 safe_deallocate_a(reduced)
1503
1504 pop_sub(kpoints_grid_reduce)
1505 end subroutine kpoints_grid_reduce
1506
1507
1508 ! --------------------------------------------------------------------------------------------
1509 subroutine kpoints_fold_to_1bz(grid, latt)
1510 type(kpoints_grid_t), intent(inout) :: grid
1511 type(lattice_vectors_t), intent(in) :: latt
1512
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
1517
1518 push_sub(kpoints_fold_to_1bz)
1519
1520 !We only need to compute the first G-vectors
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
1524 end do
1525 end do
1526
1527 do ig1 = 1, 3**grid%dim
1528 call kpoints_to_absolute(latt, gvec(:,ig1), gvec_cart(:,ig1))
1529 end do
1530
1531 do ik = 1, grid%npoints
1532
1533 dmin = 1e10_real64
1534 do ig1 = 1, 3**grid%dim
1535 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1536 d = real(sum(vec**2), real32) !Conversion to simple precision
1537 ! To avoid numerical error problems
1538 if (d < dmin) then
1539 dmin = d
1540 ig2 = ig1
1541 end if
1542 end do
1543 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1544 call kpoints_to_absolute(latt, kpt, grid%point1BZ(:, ik))
1545 end do
1546
1547 pop_sub(kpoints_fold_to_1bz)
1548 end subroutine kpoints_fold_to_1bz
1549
1550
1551 ! ---------------------------------------------------------
1552 subroutine kpoints_write_info(this, iunit, namespace, absolute_coordinates)
1553 class(kpoints_t), intent(in) :: this
1554 integer, optional, intent(in) :: iunit
1555 type(namespace_t), optional, intent(in) :: namespace
1556 logical, optional, intent(in) :: absolute_coordinates
1557
1558 integer :: ik, idir
1559 character(len=100) :: str_tmp
1560 character :: index
1561
1562 push_sub(kpoints_write_info)
1563
1564 call messages_print_with_emphasis('Brillouin zone sampling', iunit, namespace)
1565
1566 if (this%method == kpoints_monkh_pack) then
1567
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)')
1571 end do
1572 call messages_new_line()
1573
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)')
1578 end do
1579 call messages_new_line()
1580 end if
1581
1582 call messages_write('Total number of k-points =')
1583 call messages_write(this%full%npoints)
1584 call messages_new_line()
1585
1586 call messages_write('Number of symmetry-reduced k-points =')
1587 call messages_write(this%reduced%npoints)
1588
1589 call messages_info(iunit=iunit, namespace=namespace)
1590
1591 else
1592
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)
1597
1598 end if
1599
1600 call messages_new_line()
1601 call messages_write('List of k-points:')
1602 call messages_info(iunit=iunit, namespace=namespace)
1603
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)
1609 end do
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)
1614
1615 do ik = 1, kpoints_number(this)
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)
1620 else
1621 write(str_tmp,'(f12.4)') this%reduced%red_point(idir, ik)
1622 end if
1623 message(1) = trim(message(1)) // trim(str_tmp)
1624 end do
1625 write(str_tmp,'(f12.4)') kpoints_get_weight(this, ik)
1626 message(1) = trim(message(1)) // trim(str_tmp)
1627 call messages_info(1, iunit, namespace=namespace)
1628 end do
1629
1630 call messages_info(iunit=iunit, namespace=namespace)
1631
1632 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1633
1634 pop_sub(kpoints_write_info)
1635 end subroutine kpoints_write_info
1636
1637
1638 ! ---------------------------------------------------------
1639 logical pure function kpoints_point_is_gamma(this, ik) result(is_gamma)
1640 class(kpoints_t), intent(in) :: this
1641 integer, intent(in) :: ik
1642
1643 is_gamma = (maxval(abs(kpoints_get_point(this, ik))) < m_epsilon)
1644
1645 end function kpoints_point_is_gamma
1646
1647 !--------------------------------------------------------
1648
1649 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1650 type(kpoints_t), intent(in) :: this
1651 integer, intent(in) :: ik
1652
1653 if (this%use_symmetries) then
1654 num = this%num_symmetry_ops(ik)
1655 else
1656 num = 1
1657 end if
1658
1659 end function kpoints_get_num_symmetry_ops
1660 !--------------------------------------------------------
1661
1662 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1663 type(kpoints_t), intent(in) :: this
1664 integer, intent(in) :: ik
1665 integer, intent(in) :: index
1666
1667 if (this%use_symmetries) then
1668 iop = this%symmetry_ops(ik, index)
1669 else
1670 iop = 1
1671 end if
1672
1673 end function kpoints_get_symmetry_ops
1674
1675 !--------------------------------------------------------
1685 integer pure function kpoints_get_full_symmetry_op_index(this, ifull) result(iiop)
1686 class(kpoints_t), intent(in) :: this
1687 integer, intent(in) :: ifull
1688
1689 if (this%use_symmetries) then
1690 iiop = this%map_full_to_symidx(ifull)
1691 else
1692 iiop = 1
1693 end if
1694
1696
1697 !--------------------------------------------------------
1698 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1699 type(kpoints_t), intent(in) :: this
1700 integer, intent(in) :: ik
1701 integer, intent(in) :: index
1702
1703 integer :: iop
1704
1705 valid = .false.
1706 if (this%use_symmetries) then
1707 do iop = 1, this%num_symmetry_ops(ik)
1708 if (this%symmetry_ops(ik, iop) == index) then
1709 valid = .true.
1710 return
1711 end if
1712 end do
1713 else
1714 valid = .true.
1715 end if
1716
1717 end function kpoints_is_valid_symmetry
1718
1719
1720 !--------------------------------------------------------
1721 integer function kpoints_kweight_denominator(this)
1722 type(kpoints_t), intent(in) :: this
1723
1724 integer :: denom, nik, nik_skip
1725
1727
1728 nik = this%full%npoints
1729 nik_skip = this%nik_skip
1730
1731 if (this%method == kpoints_monkh_pack) then
1732 kpoints_kweight_denominator = this%full%npoints
1733 else
1735 ! NB largest reasonable value is: # k-points x 48. from space-group symmetries
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
1740 exit
1741 end if
1742 end do
1743 end if
1746 end function kpoints_kweight_denominator
1747
1748 !--------------------------------------------------------
1749 logical pure function kpoints_have_zero_weight_path(this) result(have_zerow)
1750 class(kpoints_t), intent(in) :: this
1751
1752 if (this%nik_skip > 0) then
1753 have_zerow = .true.
1754 else
1755 have_zerow = .false.
1756 end if
1759
1760 !--------------------------------------------------------
1761 integer pure function kpoints_get_kpoint_method(this)
1762 class(kpoints_t), intent(in) :: this
1763
1764 kpoints_get_kpoint_method = this%method
1765 end function kpoints_get_kpoint_method
1766
1767 !--------------------------------------------------------
1768 real(real64) pure function kpoints_get_path_coord(this, ind) result(coord)
1769 type(kpoints_t), intent(in) :: this
1770 integer, intent(in) :: ind
1771
1772 coord = this%coord_along_path(ind)
1773 end function
1774
1775
1776
1777 !--------------------------------------------------------
1778 subroutine kpoints_check_symmetries(grid, symm, dim, time_reversal, grp, namespace)
1779 type(kpoints_grid_t), intent(in) :: grid
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
1785
1786 integer, allocatable :: kmap(:)
1787 real(real64) :: kpt(dim), diff(dim)
1788 integer :: nk, ik, ik2, iop
1789 type(distributed_t) :: kpt_dist
1790
1791 push_sub(kpoints_check_symmetries)
1792
1793 nk = grid%npoints
1794
1795 !We distribute the k-points here for this routine, independently of the rest of the code
1796 call distributed_init(kpt_dist, nk, grp%comm, "kpt_check")
1797
1798 !A simple map to tell if the k-point as a matching symmetric point or not
1799 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1800
1801 do iop = 1, symmetries_number(symm)
1802 if (iop == symmetries_identity_index(symm) .and. &
1803 .not. time_reversal) cycle
1804
1805 do ik = kpt_dist%start, kpt_dist%end
1806 kmap(ik) = ik
1807 end do
1808
1809 do ik = kpt_dist%start, kpt_dist%end
1810 !We apply the symmetry
1811 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1812 !We remove potential umklapp
1813 kpt = kpt - anint(kpt + m_half*symprec)
1814
1815 ! remove (mark) k-points which already have a symmetric point
1816 do ik2 = 1, nk
1817
1818 if (iop /= symmetries_identity_index(symm)) then
1819 diff = kpt - grid%red_point(:, ik2)
1820 diff = diff - anint(diff)
1821 !We found point corresponding to the symmetric kpoint
1822 if (sum(abs(diff)) < symprec) then
1823 kmap(ik) = -ik2
1824 exit
1825 end if
1826 end if
1827
1828 if (time_reversal) then
1829 diff = kpt + grid%red_point(:, ik2)
1830 diff = diff - anint(diff)
1831 !We found point corresponding to the symmetric kpoint
1832 if (sum(abs(diff)) < symprec) then
1833 kmap(ik) = -ik2
1834 exit
1835 end if
1836 end if
1837
1838 end do
1839 !In case we have not found a symnetric k-point...
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)
1847 end if
1848 end do
1849 end do
1850
1851 safe_deallocate_a(kmap)
1852
1853 call distributed_end(kpt_dist)
1854
1857
1858 !--------------------------------------------------------
1859 logical function kpoints_is_compatible_downsampling(kpt, ik, iq) result(compatible)
1860 type(kpoints_t), intent(in) :: kpt
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)
1866
1868
1869 compatible = .true.
1870 dim = kpt%reduced%dim
1871
1872 !No downsampling. We use all k-points
1873 if (all(kpt%downsampling == 1)) then
1875 return
1876 end if
1877
1878 assert(kpt%method == kpoints_monkh_pack)
1879
1880 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1881 do idim = 1, dim
1882 !We remove potential umklapp
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.
1888 return
1889 end if
1890 end do
1891
1894
1895 ! ---------------------------------------------------------
1896 integer function kpoints_nkpt_in_path(this) result(npath)
1897 class(kpoints_t), intent(in) :: this
1898
1899 npath = 0
1900 if (allocated(this%coord_along_path)) then
1901 npath = SIZE(this%coord_along_path)
1902 end if
1903
1904 end function kpoints_nkpt_in_path
1905
1906 ! ---------------------------------------------------------
1907 logical function kpoints_gamma_only(this) result(gamma_only)
1908 class(kpoints_t), intent(in) :: this
1909
1910 push_sub(kpoints_gamma_only)
1911
1912 gamma_only = kpoints_number(this) == 1 .and. kpoints_point_is_gamma(this, 1)
1913
1914 pop_sub(kpoints_gamma_only)
1915 end function kpoints_gamma_only
1916
1917 ! ---------------------------------------------------------
1918 subroutine kpoints_lattice_vectors_update(this, new_latt)
1919 class(kpoints_t), intent(inout) :: this
1920 type(lattice_vectors_t), intent(in) :: new_latt
1921
1922 integer :: ik
1923
1925
1926 this%latt = new_latt
1927
1928 do ik = 1, this%reduced%npoints
1929 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1930 end do
1931
1932 do ik = 1, this%full%npoints
1933 call kpoints_to_absolute(this%latt, this%full%red_point(:, ik), this%full%point(:, ik))
1934 end do
1935
1937 end subroutine kpoints_lattice_vectors_update
1938
1939
1940end module kpoints_oct_m
1941
1942!! Local Variables:
1943!! mode: f90
1944!! coding: utf-8
1945!! End:
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
integer pure function kpoints_get_kpoint_method(this)
Definition: kpoints.F90:1857
subroutine, public kpoints_grid_generate(dim, naxis, nshifts, shift, kpoints, lk123)
Generates the k-points grid.
Definition: kpoints.F90:1289
subroutine, public kpoints_end(this)
Definition: kpoints.F90:1068
logical pure function kpoints_have_zero_weight_path(this)
Definition: kpoints.F90:1845
integer, parameter, public kpoints_monkh_pack
Definition: kpoints.F90:226
subroutine, public kpoints_deterministic_sort(nik_axis, kpoints, nshifts, indices)
Reorder a Monkhorst-Pack grid into a reproducible shell-based ordering.
Definition: kpoints.F90:1363
integer pure function, public kpoints_get_num_symmetry_ops(this, ik)
Definition: kpoints.F90:1745
subroutine kpoints_grid_addto(this, that)
Definition: kpoints.F90:291
real(real64) pure function, public kpoints_get_path_coord(this, ind)
Definition: kpoints.F90:1864
subroutine, public kpoints_read_user_kpoints(this, namespace, dim)
Read explicit user-defined k-points and append them to the current grids.
Definition: kpoints.F90:936
logical pure function, public kpoints_is_valid_symmetry(this, ik, index)
Definition: kpoints.F90:1794
integer function, public kpoints_kweight_denominator(this)
Definition: kpoints.F90:1817
subroutine, public kpoints_copy(kin, kout)
Definition: kpoints.F90:1174
integer pure function, public kpoints_get_full_symmetry_op_index(this, ifull)
Return symmetry-op list index for a full-grid k-point.
Definition: kpoints.F90:1781
subroutine, public kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
Generate the k-point along a path.
Definition: kpoints.F90:1415
integer, parameter, public kpoints_path
Definition: kpoints.F90:226
subroutine kpoints_print_info(this, namespace)
Definition: kpoints.F90:1090
pure real(real64) function, dimension(1:this%full%dim) kpoints_get_point(this, ik, absolute_coordinates)
Definition: kpoints.F90:1237
integer function, public kpoints_nkpt_in_path(this)
Definition: kpoints.F90:1992
logical function, public kpoints_is_compatible_downsampling(kpt, ik, iq)
Definition: kpoints.F90:1955
real(real64) pure function kpoints_get_weight(this, ik)
Definition: kpoints.F90:1253
integer function kpoints_set_method(namespace, use_symmetries, only_gamma)
Determine the k-point input method bitmask from the parsed input settings.
Definition: kpoints.F90:341
integer pure function, public kpoints_get_symmetry_ops(this, ik, index)
Definition: kpoints.F90:1758
subroutine, public kpoints_read_path(this, namespace, dim)
Read the k-points path information and generate the k-points list.
Definition: kpoints.F90:789
subroutine kpoints_grid_copy(bb, aa)
Definition: kpoints.F90:273
subroutine, public kpoints_fold_to_1bz(grid, latt)
Definition: kpoints.F90:1605
subroutine, public kpoints_init(this, namespace, symm, dim, periodic_dim, latt, grp)
Definition: kpoints.F90:419
integer function kpoints_get_equiv(this, ik)
Map a full-grid k-point index to its reduced-grid representative.
Definition: kpoints.F90:1271
subroutine, public kpoints_grid_end(this)
Definition: kpoints.F90:257
logical pure function, public kpoints_point_is_gamma(this, ik)
Definition: kpoints.F90:1735
integer, parameter, public kpoints_user
Definition: kpoints.F90:226
logical function kpoints_gamma_only(this)
Definition: kpoints.F90:2003
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.
Definition: kpoints.F90:499
subroutine, public kpoints_lattice_vectors_update(this, new_latt)
Definition: kpoints.F90:2014
subroutine, public kpoints_to_reduced(latt, kin, kout)
Definition: kpoints.F90:1160
subroutine, public kpoints_allocate_and_init(this, symm, dim, latt)
Allocate and initialise attributes that do not depend on parsed quantities.
Definition: kpoints.F90:393
integer pure function, public kpoints_number(this)
Definition: kpoints.F90:1228
subroutine kpoints_check_symmetries(grid, symm, dim, time_reversal, grp, namespace)
Definition: kpoints.F90:1874
subroutine, public kpoints_to_absolute(latt, kin, kout)
Definition: kpoints.F90:1147
subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, map_full_to_reduced, map_full_to_symidx, symm_ops, num_symm_ops)
Definition: kpoints.F90:1478
subroutine, public kpoints_grid_init(dim, this, npoints, nshifts)
Definition: kpoints.F90:236
subroutine kpoints_write_info(this, iunit, namespace, absolute_coordinates)
Definition: kpoints.F90:1648
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:463
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119
integer pure function, public symmetries_number(this)
Definition: symmetries.F90:569
logical pure function, public symmetries_have_break_dir(this)
Definition: symmetries.F90:607
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
This is defined even when running serial.
Definition: mpi.F90:144
int true(void)