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)
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
331 logical :: only_gamma, default_timereversal
332
333 push_sub(kpoints_init)
334
335 !%Variable KPointsUseSymmetries
336 !%Type logical
337 !%Default no
338 !%Section Mesh::KPoints
339 !%Description
340 !% This variable defines whether symmetries are taken into account
341 !% or not for the choice of <i>k</i>-points. If it is set to no, the <i>k</i>-point
342 !% sampling will range over the full Brillouin zone.
343 !%
344 !% When a perturbation is applied to the system, the full
345 !% symmetries of the system cannot be used. In this case you must
346 !% not use symmetries or use the <tt>SymmetryBreakDir</tt> to tell
347 !% Octopus the direction of the perturbation (for the moment this
348 !% has to be done by hand by the user, in the future it will be
349 !% automatic).
350 !%
351 !%End
352 call parse_variable(namespace, 'KPointsUseSymmetries', .false., this%use_symmetries)
353
354 !%Variable KPointsUseTimeReversal
355 !%Type logical
356 !%Section Mesh::KPoints
357 !%Description
358 !% If symmetries are used to reduce the number of <i>k</i>-points,
359 !% this variable defines whether time-reversal symmetry is taken
360 !% into account or not. If it is set to no, the <i>k</i>-point
361 !% sampling will not be reduced according to time-reversal
362 !% symmetry.
363 !%
364 !% The default is yes, unless symmetries are broken in one
365 !% direction by the <tt>SymmetryBreakDir</tt> block.
366 !%
367 !% Warning: For time propagation runs with an external field,
368 !% time-reversal symmetry should not be used.
369 !%
370 !%End
371 default_timereversal = this%use_symmetries .and. .not. symmetries_have_break_dir(symm)
372 call parse_variable(namespace, 'KPointsUseTimeReversal', default_timereversal, this%use_time_reversal)
373
374 only_gamma = (periodic_dim == 0)
375 this%method = kpoints_set_method(namespace, this%use_symmetries, only_gamma)
376 call kpoints_allocate_and_init(this, symm, dim, latt)
377
378 if (only_gamma) then
379 call kpoints_read_mp(this, namespace, symm, dim, gamma_only=.true.)
380 pop_sub(kpoints_init)
381 return
382 end if
383
384 if (bitand(this%method, kpoints_monkh_pack) /= 0) then
385 call kpoints_read_mp(this, namespace, symm, dim, gamma_only=.false.)
386 end if
387
388 if (bitand(this%method, kpoints_user) /= 0) then
389 call kpoints_read_user_kpoints(this, namespace, dim)
390 end if
391
392 if (bitand(this%method, kpoints_path) /= 0) then
393 call kpoints_read_path(this, namespace, dim)
394 end if
395
396 call kpoints_print_info(this, namespace)
397
398 pop_sub(kpoints_init)
399 end subroutine kpoints_init
400
402 subroutine kpoints_read_mp(this, namespace, symm, dim, gamma_only)
403 type(kpoints_t), intent(inout) :: this
404 type(namespace_t), intent(in) :: namespace
405 type(symmetries_t), intent(in) :: symm
406 integer, intent(in) :: dim
407 logical, intent(in) :: gamma_only
408
409 logical :: gamma_only_
410 integer :: ii, ik, is, ncols, nshifts
411 type(block_t) :: blk
412 integer, allocatable :: symm_ops(:, :), num_symm_ops(:)
413 real(real64), allocatable :: shifts(:, :)
414
415 push_sub(kpoints_read_mp)
416
417 call messages_obsolete_variable(namespace, 'KPointsMonkhorstPack', 'KPointsGrid')
419 !%Variable KPointsGrid
420 !%Type block
421 !%Default <math>\Gamma</math>-point only
422 !%Section Mesh::KPoints
423 !%Description
424 !% When this block is given (and the <tt>KPoints</tt> block is not present),
425 !% <i>k</i>-points are distributed in a uniform grid, according to a modified
426 !% version of the Monkhorst-Pack scheme. For the original MP scheme, see
427 !% James D. Pack and Hendrik J. Monkhorst,
428 !% <i>Phys. Rev. B</i> <b>13</b>, 5188 (1976) and <i>Phys. Rev. B</i> <b>16</b>, 1748 (1977).
429 !%
430 !% The number of columns should be equal to <tt>Dimensions</tt>,
431 !% but the grid and shift numbers should be 1 and zero in finite directions.
432 !%
433 !% The first row of the block is a set of integers defining
434 !% the number of <i>k</i>-points to be used along each direction
435 !% in reciprocal space. The numbers refer to the whole Brillouin
436 !% zone, and the actual number of <i>k</i>-points is usually
437 !% reduced exploiting the symmetries of the system. By default
438 !% the grid will always include the <math>\Gamma</math>-point.
439 !%
440 !% Optional rows can be added to specify multiple shifts in the <i>k</i>-points (between 0.0 and 1.0),
441 !% in units of the Brillouin zone divided by the number in the first row.
442 !% Please note that without specifying any shift, an implicit shift of -0.5 is added for odd number
443 !% of k-points, such that the Gamma point is always included.
444 !%
445 !% For example, the following input samples the BZ with 100 points in the
446 !% <i>xy</i>-plane of reciprocal space:
447 !%
448 !% <tt>%KPointsGrid
449 !% <br>&nbsp;&nbsp;10 | 10 | 1
450 !% <br>%</tt>
451 !%
452 !% is equivalent to
453 !%
454 !% <tt>%KPointsGrid
455 !% <br> 10 | 10 | 1
456 !% <br> 0 | 0 | -0.5
457 !% <br>%</tt>
458 !%
459 !%End
460
461 gamma_only_ = gamma_only
462 if (.not. gamma_only_) then
463 gamma_only_ = (parse_block(namespace, 'KPointsGrid', blk) /= 0)
464 end if
465
466 this%nik_axis = 1
467
468 if (.not. gamma_only_) then
469 nshifts = max(parse_block_n(blk)-1,1)
470 else
471 nshifts = 1
472 end if
473 safe_allocate(shifts(1:dim,1:nshifts))
474 shifts = m_zero
475
476 if (.not. gamma_only_) then
477 ncols = parse_block_cols(blk, 0)
478 if (ncols /= dim) then
479 write(message(1),'(a,i3,a,i3)') 'KPointsGrid first row has ', ncols, ' columns but should have ', dim
480 if (ncols < dim) then
481 call messages_fatal(1, namespace=namespace)
482 else
483 write(message(2),'(a)') 'Continuing, but ignoring the additional values.'
484 call messages_warning(2, namespace=namespace)
485 end if
486 end if
487 do ii = 1, dim
488 call parse_block_integer(blk, 0, ii - 1, this%nik_axis(ii))
489 end do
490
491 if (any(this%nik_axis < 1)) then
492 message(1) = 'Input: KPointsGrid is not valid.'
493 call messages_fatal(1, namespace=namespace)
494 end if
495
496 if (parse_block_n(blk) > 1) then ! we have a shift, or even more
497 ncols = parse_block_cols(blk, 1)
498 if (ncols /= dim) then
499 write(message(1),'(a,i3,a,i3)') 'KPointsGrid shift has ', ncols, ' columns but must have ', dim
500 call messages_fatal(1, namespace=namespace)
501 end if
502 do is = 1, nshifts
503 do ii = 1, dim
504 call parse_block_float(blk, is, ii - 1, shifts(ii,is))
505 end do
506 end do
507 else
508 !We include a default 0.5 shift for odd number of k-points
509 do ii = 1, dim
510 if (mod(this%nik_axis(ii), 2) /= 0) then
511 shifts(ii,1) = m_half
512 end if
513 end do
514 end if
515
516 call parse_block_end(blk)
517 else
518 shifts(:, 1) = -m_half
519 end if
520
521 !%Variable QPointsGrid
522 !%Type block
523 !%Default KPointsGrid
524 !%Section Mesh::KPoints
525 !%Description
526 !% This block allows to define a q-point grid used for the calculation of the Fock operator
527 !% with k-points. The <i>q</i>-points are distributed in a uniform grid, as done for the
528 !% <tt>KPointsGrid</tt> variable.
529 !% See J. Chem Phys. 124, 154709 (2006) for details
530 !%
531 !% For each dimension, the number of q point must be a divider of the number of k point
532 !%
533 !% <tt>%QPointsGrid
534 !% <br>&nbsp;&nbsp;2 | 2 | 1
535 !% <br>%</tt>
536 !%
537 !% At the moment, this is not compatible with k-point symmetries.
538 !%
539 !%End
540 this%niq_axis(:) = this%nik_axis(:)
541 this%downsampling(:) = 1
542 if (parse_is_defined(namespace, 'QPointsGrid')) then
543 if (parse_block(namespace, 'QPointsGrid', blk) == 0) then
544 ncols = parse_block_cols(blk, 0)
545 if (ncols /= dim) then
546 write(message(1),'(a,i3,a,i3)') 'QPointsGrid first row has ', ncols, ' columns but must have ', dim
547 call messages_fatal(1, namespace=namespace)
548 end if
549 do ii = 1, dim
550 call parse_block_integer(blk, 0, ii - 1, this%niq_axis(ii))
551 end do
552
553 if (any(this%nik_axis/this%niq_axis /= nint(this%nik_axis/real(this%niq_axis)))) then
554 message(1) = 'Input: QPointsGrid is not compatible with the KPointsGrid.'
555 call messages_fatal(1, namespace=namespace)
556 end if
557
558 this%downsampling = this%nik_axis/this%niq_axis
559
560 if (any(this%downsampling /= 1) .and. this%use_symmetries) then
561 call messages_not_implemented('QPointsGrid together with k-point symmetries', namespace=namespace)
562 end if
563
564 call parse_block_end(blk)
565 end if
566 end if
567
568 call kpoints_grid_init(dim, this%full, product(this%nik_axis)*nshifts, nshifts)
569
570 !We move the k-points into this%shifts
571 this%full%shifts(:, :) = shifts(:, :)
572 safe_deallocate_a(shifts)
573
574 ! The grid labels are kept, as they give the position of a k-point on the
575 ! Monkhorst-Pack grid without having to recover it from its coordinates.
576 safe_allocate(this%lk123(1:this%full%npoints, 1:dim))
577 call kpoints_grid_generate(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
578 lk123 = this%lk123)
579
580 do ik = 1, this%full%npoints
581 call kpoints_to_absolute(this%latt, this%full%red_point(:, ik), this%full%point(:, ik))
582 end do
583
584 this%full%weight = m_one / this%full%npoints
585
586 if (this%use_symmetries) then
587 message(1) = "Checking if the generated full k-point grid is symmetric"
588 call messages_info(1, namespace=namespace)
589 call kpoints_check_symmetries(this%full, symm, dim, this%use_time_reversal, namespace)
590 end if
591
592 call kpoints_grid_copy(this%full, this%reduced)
593
594 if (this%use_symmetries) then
595 safe_allocate(num_symm_ops(1:this%full%npoints))
596
597 if (this%use_time_reversal) then
598 safe_allocate(symm_ops(1:this%full%npoints, 1:2*symmetries_number(symm)))
599 else
600 safe_allocate(symm_ops(1:this%full%npoints, 1:symmetries_number(symm)))
601 end if
602
603 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
604 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
605 call kpoints_grid_reduce(symm, this%use_time_reversal, &
606 this%reduced%npoints, dim, this%reduced%red_point, this%reduced%weight, this%map_full_to_reduced, &
607 this%map_full_to_symidx, symm_ops, num_symm_ops)
608
609 assert(maxval(num_symm_ops) >= 1)
610 if (this%use_time_reversal) then
611 assert(maxval(num_symm_ops) <= 2*symmetries_number(symm))
612 else
613 assert(maxval(num_symm_ops) <= symmetries_number(symm))
614 end if
615
616 ! the total number of symmetry operations in the list has to be equal to the number of k-points
617 assert(sum(num_symm_ops(1:this%reduced%npoints)) == this%full%npoints)
618
619 do ik = 1, this%reduced%npoints
620 assert(all(symm_ops(ik, 1:num_symm_ops(ik)) <= symm%nops))
621 end do
622
623 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)))
624 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
625
626 this%num_symmetry_ops(1:this%reduced%npoints) = num_symm_ops(1:this%reduced%npoints)
627 this%symmetry_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops)) = &
628 symm_ops(1:this%reduced%npoints, 1:maxval(num_symm_ops))
629
630 safe_deallocate_a(num_symm_ops)
631 safe_deallocate_a(symm_ops)
632 else
633 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
634 safe_allocate(this%symmetry_ops(1:this%reduced%npoints, 1))
635 this%num_symmetry_ops(1:this%reduced%npoints) = 1
636 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
637 safe_allocate(this%map_full_to_reduced(1:this%full%npoints))
638 do ik = 1, this%full%npoints
639 this%map_full_to_reduced(ik) = ik
640 end do
641 safe_allocate(this%map_full_to_symidx(1:this%full%npoints))
642 this%map_full_to_symidx(:) = 1
643 end if
644
645 do ik = 1, this%reduced%npoints
646 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
647 end do
648
649 call kpoints_fold_to_1bz(this%full, this%latt)
650 call kpoints_fold_to_1bz(this%reduced, this%latt)
651
652 block
653 integer(int64) :: dos_method, smearing_function
654 logical :: use_simplex, use_simplex_opt
655
656 call parse_variable(namespace, 'DOSMethod', option__dosmethod__smear, dos_method)
657 call parse_variable(namespace, 'SmearingFunction', option__smearingfunction__semiconducting, smearing_function)
658
659 use_simplex = dos_method == option__dosmethod__tetrahedra .or. &
660 smearing_function == option__smearingfunction__tetrahedra
661 use_simplex_opt = dos_method == option__dosmethod__tetrahedra_opt .or. &
662 smearing_function == option__smearingfunction__tetrahedra_opt
663
664 if (use_simplex .and. use_simplex_opt) then
665 call messages_not_implemented("DOSMethod and SmearingFunction with different tetrahedron methods", namespace=namespace)
666 end if
667
668 if (use_simplex .or. use_simplex_opt) then
669 safe_deallocate_p(this%full%simplex)
670 safe_deallocate_p(this%reduced%simplex)
671 end if
672
673 if (use_simplex) then
674 this%full%simplex => simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
675 opt = .false.)
676 this%reduced%simplex => simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
677 equiv = this%map_full_to_reduced, opt = .false.)
678 elseif (use_simplex_opt) then
679 this%full%simplex => simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
680 opt = .true.)
681 this%reduced%simplex => simplex_t(dim, this%nik_axis, this%full%nshifts, this%full%shifts, this%full%red_point, &
682 equiv = this%map_full_to_reduced, opt = .true.)
683 end if
684 end block
685
686 pop_sub(kpoints_read_mp)
687 end subroutine kpoints_read_mp
688
689
691 subroutine kpoints_read_path(this, namespace, dim)
692 type(kpoints_t), intent(inout) :: this
693 type(namespace_t), intent(in) :: namespace
694 integer, intent(in) :: dim
695
696 type(block_t) :: blk
697 integer :: nshifts, nkpoints, nhighsympoints, nsegments
698 integer :: icol, ik, idir, ncols, npoints
699 integer, allocatable :: resolution(:)
700 real(real64), allocatable :: highsympoints(:, :)
701 type(kpoints_grid_t) :: path_kpoints_grid
702 integer, allocatable :: symm_ops(:, :), num_symm_ops(:)
703
704 push_sub(kpoints_read_path)
705
706 !%Variable KPointsPath
707 !%Type block
708 !%Section Mesh::KPoints
709 !%Description
710 !% When this block is given, <i>k</i>-points are generated along a path
711 !% defined by the points of the list.
712 !% The points must be given in reduced coordinates.
713 !%
714 !% The first row of the block is a set of integers defining
715 !% the number of <i>k</i>-points for each segments of the path.
716 !% The number of columns should be equal to <tt>Dimensions</tt>,
717 !% and the k-points coordinate should be zero in finite directions.
718 !%
719 !% For example, the following input samples the BZ with 15 points:
720 !%
721 !% <tt>%KPointsPath
722 !% <br>&nbsp;&nbsp;10 | 5
723 !% <br>&nbsp;&nbsp; 0 | 0 | 0
724 !% <br>&nbsp;&nbsp; 0.5 | 0 | 0
725 !% <br>&nbsp;&nbsp; 0.5 | 0.5 | 0.5
726 !% <br>%</tt>
727 !%
728 !%End
729
730 if (parse_block(namespace, 'KPointsPath', blk) /= 0) then
731 write(message(1),'(a)') 'Internal error while reading KPointsPath.'
732 call messages_fatal(1, namespace=namespace)
733 end if
734
735 ! There is one high symmetry k-point per line
736 nsegments = parse_block_cols(blk, 0)
737 nhighsympoints = parse_block_n(blk) - 1
738 if (nhighsympoints /= nsegments + 1) then
739 write(message(1),'(a,i3,a,i3)') 'The first row of KPointsPath is not compatible with the number of specified k-points.'
740 call messages_fatal(1, namespace=namespace)
741 end if
742
743 safe_allocate(resolution(1:nsegments))
744 do icol = 1, nsegments
745 call parse_block_integer(blk, 0, icol-1, resolution(icol))
746 end do
747 !Total number of points in the segment
748 nkpoints = sum(resolution) + 1
749
750 safe_allocate(highsympoints(1:dim, 1:nhighsympoints))
751 do ik = 1, nhighsympoints
752 ncols = parse_block_cols(blk, ik)
753 if (ncols /= dim) then
754 write(message(1),'(a,i8,a,i3,a,i3)') 'KPointsPath row ', ik, ' has ', ncols, ' columns but must have ', dim
755 call messages_fatal(1, namespace=namespace)
756 end if
757
758 do idir = 1, dim
759 call parse_block_float(blk, ik, idir-1, highsympoints(idir, ik))
760 end do
761 end do
762
763 call parse_block_end(blk)
764
765 !We do not have shifts
766 nshifts = 1
767 call kpoints_grid_init(dim, path_kpoints_grid, nkpoints, nshifts)
768
769 ! For the output of band-structures
770 safe_allocate(this%coord_along_path(1:nkpoints))
771
772 call kpoints_path_generate(dim, this%latt, nkpoints, nsegments, resolution, highsympoints, path_kpoints_grid%point, &
773 this%coord_along_path)
774
775 safe_deallocate_a(resolution)
776 safe_deallocate_a(highsympoints)
777
778 !Use zero weight for the path so that it can be used with any kind of calculation mode
779 !without interfering with the physical BZ integral.
780 if (this%method == kpoints_path) then
781 path_kpoints_grid%weight = m_one/path_kpoints_grid%npoints
782 else
783 path_kpoints_grid%weight = m_zero
784 this%nik_skip = this%nik_skip + path_kpoints_grid%npoints
785 end if
787 !The points have been generated in absolute coordinates
788 do ik = 1, path_kpoints_grid%npoints
789 call kpoints_to_reduced(this%latt, path_kpoints_grid%point(:, ik), path_kpoints_grid%red_point(:, ik))
790 end do
791
792 call kpoints_fold_to_1bz(path_kpoints_grid, this%latt)
793
794 !We need to copy the arrays containing the information on the symmetries
795 !Before calling kpoints_grid_addto
796 if (allocated(this%symmetry_ops)) then
797 npoints = this%reduced%npoints
798 safe_allocate(num_symm_ops(1:npoints))
799 safe_allocate(symm_ops(1:npoints, 1:maxval(this%num_symmetry_ops)))
800
801 num_symm_ops(1:npoints) = this%num_symmetry_ops(1:npoints)
802 symm_ops(1:npoints, 1:maxval(num_symm_ops)) = &
803 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops))
804 end if
805
806 call kpoints_grid_addto(this%full , path_kpoints_grid)
807 call kpoints_grid_addto(this%reduced, path_kpoints_grid)
808
809 if (allocated(this%symmetry_ops)) then
810 safe_deallocate_a(this%num_symmetry_ops)
811 safe_deallocate_a(this%symmetry_ops)
812 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
813 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:maxval(num_symm_ops)))
814
815 this%num_symmetry_ops(1:npoints) = num_symm_ops(1:npoints)
816 this%symmetry_ops(1:npoints, 1:maxval(num_symm_ops)) = &
817 symm_ops(1:npoints, 1:maxval(num_symm_ops))
818 this%num_symmetry_ops(npoints+1:this%reduced%npoints) = 1
819 this%symmetry_ops(npoints+1:this%reduced%npoints, 1) = 1
820
821 safe_deallocate_a(num_symm_ops)
822 safe_deallocate_a(symm_ops)
823 else if(this%use_symmetries) then ! If symmetries are activated but no KPointsGrid specified
824 safe_allocate(this%num_symmetry_ops(1:this%reduced%npoints))
825 safe_allocate(this%symmetry_ops(1:this%reduced%npoints,1:1))
826
827 this%num_symmetry_ops(1:this%reduced%npoints) = 1
828 this%symmetry_ops(1:this%reduced%npoints, 1) = 1
829 end if
830
831 call kpoints_grid_end(path_kpoints_grid)
832
833 pop_sub(kpoints_read_path)
834 end subroutine kpoints_read_path
835
836
838 subroutine kpoints_read_user_kpoints(this, namespace, dim)
839 type(kpoints_t), intent(inout) :: this
840 type(namespace_t), intent(in) :: namespace
841 integer, intent(in) :: dim
842
843 type(block_t) :: blk
844 logical :: reduced
845 integer :: ik, idir
846 real(real64) :: weight_sum
847 type(kpoints_grid_t) :: user_kpoints_grid
848
850
851 !%Variable KPoints
852 !%Type block
853 !%Section Mesh::KPoints
854 !%Description
855 !% This block defines an explicit set of <i>k</i>-points and their weights for
856 !% a periodic-system calculation. The first column is the weight
857 !% of each <i>k</i>-point and the following are the components of the <i>k</i>-point
858 !% vector. You only need to specify the components for the
859 !% periodic directions. Note that the <i>k</i>-points should be given in
860 !% Cartesian coordinates (not in reduced coordinates), in the units of inverse length.
861 !% The weights will be renormalized so they sum to 1 (and must be rational numbers).
862 !%
863 !% For example, if you want to include only the Gamma point, you can
864 !% use:
865 !%
866 !% <tt>%KPoints
867 !% <br>&nbsp;&nbsp;1.0 | 0 | 0 | 0
868 !% <br>%</tt>
869 !%
870 !%End
871
872 !%Variable KPointsReduced
873 !%Type block
874 !%Section Mesh::KPoints
875 !%Description
876 !% Same as the block <tt>KPoints</tt> but this time the input is given in reduced
877 !% coordinates, <i>i.e.</i>
878 !% what <tt>Octopus</tt> writes in a line in the ground-state standard output as
879 !%
880 !% <tt>#k = 1, k = ( 0.154000, 0.154000, 0.154000)</tt>.
881 !%End
882
883 reduced = .false.
884 if (parse_block(namespace, 'KPoints', blk) /= 0) then
885 if (parse_block(namespace, 'KPointsReduced', blk) == 0) then
886 reduced = .true.
887 else
888 ! This case should really never happen
889 write(message(1),'(a)') 'Internal error loading user-defined k-point list.'
890 call messages_fatal(1, namespace=namespace)
891 end if
892 end if
893
894 call kpoints_grid_init(dim, user_kpoints_grid, parse_block_n(blk), 1)
895
896 user_kpoints_grid%red_point = m_zero
897 user_kpoints_grid%point = m_zero
898 user_kpoints_grid%weight = m_zero
899 user_kpoints_grid%shifts = m_zero
900
901 if (reduced) then
902 do ik = 1, user_kpoints_grid%npoints
903 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
904 do idir = 1, dim
905 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%red_point(idir, ik))
906 end do
907 ! generate also the absolute coordinates
908 call kpoints_to_absolute(this%latt, user_kpoints_grid%red_point(:, ik), user_kpoints_grid%point(:, ik))
909 end do
910 else
911 do ik = 1, user_kpoints_grid%npoints
912 call parse_block_float(blk, ik - 1, 0, user_kpoints_grid%weight(ik))
913 do idir = 1, dim
914 call parse_block_float(blk, ik - 1, idir, user_kpoints_grid%point(idir, ik), unit_one/units_inp%length)
915 end do
916 ! generate also the reduced coordinates
917 call kpoints_to_reduced(this%latt, user_kpoints_grid%point(:, ik), user_kpoints_grid%red_point(:, ik))
918 end do
919 end if
920 call parse_block_end(blk)
921
922 this%nik_skip = 0
923 if (any(user_kpoints_grid%weight < m_epsilon)) then
924 call messages_experimental('K-points with zero weight')
925 message(1) = "Found k-points with zero weight. They are excluded from density calculation"
926 call messages_warning(1, namespace=namespace)
927 ! count k-points with zero weight and make sure the points are given in
928 ! a block after all regular k-points. This is for convenience, so they can be skipped
929 ! easily and not a big restraint for the user who has to provide the k-points
930 ! explicitly anyway.
931 do ik=1,user_kpoints_grid%npoints
932 if (user_kpoints_grid%weight(ik) < m_epsilon) then
933 ! check there are no points with positive weight following a zero weighted one
934 if (ik < user_kpoints_grid%npoints) then
935 if (user_kpoints_grid%weight(ik+1) > m_epsilon) then
936 message(1) = "K-points with zero weight must follow all regular k-points in a block"
937 call messages_fatal(1, namespace=namespace)
938 end if
939 end if
940 this%nik_skip = this%nik_skip + 1
941 user_kpoints_grid%weight(ik) = m_zero
942 end if
943 end do
944 end if
945 ! renormalize weights
946 weight_sum = sum(user_kpoints_grid%weight)
947 if (weight_sum < m_epsilon) then
948 message(1) = "k-point weights must sum to a positive number."
949 call messages_fatal(1, namespace=namespace)
950 end if
951 user_kpoints_grid%weight = user_kpoints_grid%weight / weight_sum
952
953 ! for the moment we do not apply symmetries to user kpoints
954 ! call kpoints_grid_copy(this%full, this%reduced)
955
956 call kpoints_fold_to_1bz(user_kpoints_grid, this%latt)
957
958 call kpoints_grid_addto(this%full , user_kpoints_grid)
959 call kpoints_grid_addto(this%reduced, user_kpoints_grid)
960
961 write(message(1), '(a,i4,a)') 'Input: ', user_kpoints_grid%npoints, ' k-points were read from the input file'
962 call messages_info(1, namespace=namespace)
963
964 call kpoints_grid_end(user_kpoints_grid)
965
967 end subroutine kpoints_read_user_kpoints
968
969 ! ---------------------------------------------------------
970 subroutine kpoints_end(this)
971 type(kpoints_t), intent(inout) :: this
972
973 push_sub(kpoints_end)
974
975 call kpoints_grid_end(this%full)
976 call kpoints_grid_end(this%reduced)
977
978 safe_deallocate_a(this%nik_axis)
979 safe_deallocate_a(this%niq_axis)
980 safe_deallocate_a(this%lk123)
981 safe_deallocate_a(this%downsampling)
982 safe_deallocate_a(this%symmetry_ops)
983 safe_deallocate_a(this%num_symmetry_ops)
984 safe_deallocate_a(this%map_full_to_reduced)
985 safe_deallocate_a(this%map_full_to_symidx)
986 safe_deallocate_a(this%coord_along_path)
987
988 pop_sub(kpoints_end)
989 end subroutine kpoints_end
990
991
992 subroutine kpoints_print_info(this, namespace)
993 type(kpoints_t), intent(in) :: this
994 type(namespace_t), intent(in) :: namespace
995
996 integer :: idir, is, ik, dim
997 character(len=100) :: str_tmp
998
999 push_sub(kpoints_print_info)
1000
1001 dim = this%reduced%dim
1002
1003 if (bitand(this%method, kpoints_monkh_pack) /= 0) then
1004 write(message(1),'(a)') ' '
1005 write(message(2),'(1x,i5,a)') this%reduced%npoints, ' k-points generated from parameters :'
1006 write(message(3),'(1x,a)') '---------------------------------------------------'
1007 write(message(4),'(4x,a)') 'n ='
1008 do idir = 1, dim
1009 write(str_tmp,'(i5)') this%nik_axis(idir)
1010 message(4) = trim(message(4)) // trim(str_tmp)
1011 end do
1012 call messages_info(4, namespace=namespace)
1013
1014 do is = 1, this%reduced%nshifts
1015 write(message(1),'(a)') ' '
1016 write(message(2),'(4x,a,i1,a)') 's', is, ' ='
1017 do idir = 1, dim
1018 write(str_tmp,'(f6.2)') this%reduced%shifts(idir,is)
1019 message(2) = trim(message(2)) // trim(str_tmp)
1020 end do
1021 call messages_info(2, namespace=namespace)
1022 end do
1023 end if
1024
1025 write(message(1),'(a)') ' '
1026 write(message(2),'(a)') ' index | weight | coordinates |'
1027 call messages_info(2, namespace=namespace)
1028
1029 do ik = 1, this%reduced%npoints
1030 write(str_tmp,'(i8,a,f12.6,a)') ik, " | ", this%reduced%weight(ik), " |"
1031 message(1) = str_tmp
1032 do idir = 1, dim
1033 write(str_tmp,'(f12.6)') this%reduced%red_point(idir, ik)
1034 message(1) = trim(message(1)) // trim(str_tmp)
1035 end do
1036 write(str_tmp,'(a)') " |"
1037 message(1) = trim(message(1)) // trim(str_tmp)
1038 call messages_info(1, namespace=namespace)
1039 end do
1040
1041 write(message(1),'(a)') ' '
1042 call messages_info(1, namespace=namespace)
1043
1044 pop_sub(kpoints_print_info)
1045
1046 end subroutine kpoints_print_info
1047
1048 ! ---------------------------------------------------------
1049 subroutine kpoints_to_absolute(latt, kin, kout)
1050 type(lattice_vectors_t), intent(in) :: latt
1051 real(real64), intent(in) :: kin(:)
1052 real(real64), intent(out) :: kout(:)
1053
1054 push_sub(kpoints_to_absolute)
1055
1056 kout = matmul(latt%klattice, kin)
1057
1058 pop_sub(kpoints_to_absolute)
1059 end subroutine kpoints_to_absolute
1060
1061 ! ---------------------------------------------------------
1062 subroutine kpoints_to_reduced(latt, kin, kout)
1063 type(lattice_vectors_t), intent(in) :: latt
1064 real(real64), intent(in) :: kin(:)
1065 real(real64), intent(out) :: kout(:)
1066
1067 push_sub(kpoints_to_reduced)
1068
1069 kout = matmul(kin, latt%rlattice) / (m_two*m_pi)
1070
1071 pop_sub(kpoints_to_reduced)
1072 end subroutine kpoints_to_reduced
1073
1074
1075 ! ---------------------------------------------------------
1076 subroutine kpoints_copy(kin, kout)
1077 type(kpoints_t), intent(in) :: kin
1078 type(kpoints_t), intent(inout) :: kout
1079
1080 push_sub(kpoints_copy)
1081
1082 call kpoints_end(kout)
1083
1084 kout%method = kin%method
1085
1086 call kpoints_grid_copy(kin%full, kout%full)
1087 call kpoints_grid_copy(kin%reduced, kout%reduced)
1088
1089 kout%use_symmetries = kin%use_symmetries
1090 kout%use_time_reversal = kin%use_time_reversal
1091
1092 safe_allocate(kout%nik_axis(1:kin%full%dim))
1093 safe_allocate(kout%niq_axis(1:kin%full%dim))
1094 safe_allocate(kout%downsampling(1:kin%full%dim))
1095 kout%nik_axis(:) = kin%nik_axis(:)
1096 kout%niq_axis(:) = kin%niq_axis(:)
1097 kout%downsampling(:) = kin%downsampling(:)
1098
1099 if (allocated(kin%lk123)) then
1100 safe_allocate(kout%lk123(1:kin%full%npoints, 1:kin%full%dim))
1101 kout%lk123(:, :) = kin%lk123(:, :)
1102 end if
1103
1104 if (allocated(kin%coord_along_path)) then
1105 safe_allocate(kout%coord_along_path(1:kin%full%npoints))
1106 kout%coord_along_path(1:kin%full%npoints) = kin%coord_along_path(1:kin%full%npoints)
1107 end if
1108
1109 if (allocated(kin%symmetry_ops)) then
1110 safe_allocate(kout%num_symmetry_ops(1:kin%reduced%npoints))
1111 safe_allocate(kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)))
1112 kout%num_symmetry_ops(1:kin%reduced%npoints) = kin%num_symmetry_ops(1:kin%reduced%npoints)
1113 kout%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops)) = &
1114 kin%symmetry_ops(1:kin%reduced%npoints, 1:maxval(kin%num_symmetry_ops))
1115 end if
1116 if (allocated(kin%map_full_to_symidx)) then
1117 safe_allocate(kout%map_full_to_symidx(1:kin%full%npoints))
1118 kout%map_full_to_symidx(1:kin%full%npoints) = kin%map_full_to_symidx(1:kin%full%npoints)
1119 end if
1120 if (allocated(kin%map_full_to_reduced)) then
1121 safe_allocate(kout%map_full_to_reduced(1:kin%full%npoints))
1122 kout%map_full_to_reduced(1:kin%full%npoints) = kin%map_full_to_reduced(1:kin%full%npoints)
1123 end if
1124
1125 pop_sub(kpoints_copy)
1126 end subroutine kpoints_copy
1127
1128
1129 ! ----------------------------------------------------------
1130 integer pure function kpoints_number(this) result(number)
1131 type(kpoints_t), intent(in) :: this
1132
1133 number = this%reduced%npoints
1134
1135 end function kpoints_number
1136
1137
1138 ! ----------------------------------------------------------
1139 pure function kpoints_get_point(this, ik, absolute_coordinates) result(point)
1140 class(kpoints_t), intent(in) :: this
1141 integer, intent(in) :: ik
1142 logical, optional, intent(in) :: absolute_coordinates
1143 real(real64) :: point(1:this%full%dim)
1145 if (optional_default(absolute_coordinates, .true.)) then
1146 point(1:this%full%dim) = this%reduced%point(1:this%full%dim, ik)
1147 else
1148 point(1:this%full%dim) = this%reduced%red_point(1:this%full%dim, ik)
1149 end if
1150
1151 end function kpoints_get_point
1152
1153
1154 ! ----------------------------------------------------------
1155 real(real64) pure function kpoints_get_weight(this, ik) result(weight)
1156 class(kpoints_t), intent(in) :: this
1157 integer, intent(in) :: ik
1158
1159 weight = this%reduced%weight(ik)
1160
1161 end function kpoints_get_weight
1162
1163
1164 ! ----------------------------------------------------------
1173 integer function kpoints_get_equiv(this, ik) result(equiv)
1174 class(kpoints_t), intent(in) :: this
1175 integer, intent(in) :: ik
1176
1177 assert(allocated(this%map_full_to_reduced))
1178 equiv = this%map_full_to_reduced(ik)
1179
1180 end function kpoints_get_equiv
1181
1182
1183 ! ----------------------------------------------------------
1191 subroutine kpoints_grid_generate(dim, naxis, nshifts, shift, kpoints, lk123)
1192 integer, intent(in) :: dim
1193 integer, intent(in) :: naxis(1:dim)
1194 integer, intent(in) :: nshifts
1195 real(real64), intent(in) :: shift(:, :)
1196 real(real64), intent(out) :: kpoints(:, :)
1197 integer, optional, intent(out) :: lk123(:, :)
1198 ! !< running from 0 to naxis(1:3).
1199
1200 real(real64) :: dx(dim)
1201 integer :: ii, jj, divisor, ik, idir, npoints, is, ix(dim)
1202 integer, allocatable :: lk123_(:, :), idx(:)
1203
1204 push_sub(kpoints_grid_generate)
1205
1206 dx = m_one/(m_two*naxis)
1207
1208 npoints = product(naxis)
1209
1210 safe_allocate(idx(1:npoints*nshifts))
1211 if (present(lk123)) then
1212 safe_allocate(lk123_(1:npoints*nshifts,1:dim))
1213 end if
1214
1215 do is = 1, nshifts
1216 do ii = 0, npoints - 1
1217 ik = npoints*is - ii
1218 jj = ii
1219 divisor = npoints
1220
1221 do idir = 1, dim
1222 divisor = divisor / naxis(idir)
1223 ix(idir) = jj / divisor + 1
1224 jj = mod(jj, divisor)
1226 kpoints(idir, ik) = (m_two*ix(idir) - m_one*naxis(idir) + m_two*shift(idir,is))*dx(idir)
1227 !A default shift of +0.5 is including in case if (mod(naxis(idir), 2) /= 0)
1228
1229 !bring back point to first Brillouin zone, except for points at 1/2
1230 if (abs(kpoints(idir, ik) - m_half) > 1e-14_real64) then
1231 kpoints(idir, ik) = mod(kpoints(idir, ik) + m_half, m_one) - m_half
1232 end if
1233
1234 end do
1235 if (present(lk123)) then
1236 lk123_(ik, :) = ix
1237 idx(ik) = ik
1238 end if
1239 end do
1240 end do
1241
1242 call kpoints_deterministic_sort(naxis, kpoints, nshifts=nshifts, indices=idx)
1243
1244 if (present(lk123)) then
1245 do ik = 1, npoints*nshifts
1246 lk123(ik,:) = lk123_(idx(ik),:)
1247 end do
1248 safe_deallocate_a(lk123_)
1249 end if
1251 safe_deallocate_a(idx)
1252
1253 pop_sub(kpoints_grid_generate)
1254
1255 end subroutine kpoints_grid_generate
1256
1257
1265 subroutine kpoints_deterministic_sort(nik_axis, kpoints, nshifts, indices)
1266 integer, intent(in ) :: nik_axis(:)
1267 real(real64), intent(inout) :: kpoints(:, :)
1268 ! In: Unsorted
1269 ! Out: Sorted
1270 integer, optional, intent(in) :: nshifts
1271 integer, optional, intent(out) :: indices(:)
1272 ! original column chosen for sorted position ik_sorted
1273
1274 integer :: ndim, nk, ik, nshifts_
1275 real(real64) :: dk(size(kpoints, 1))
1276 integer, allocatable :: idx(:)
1277 real(real64), allocatable :: shell(:), kpoints_unsorted(:, :)
1278
1280
1281 ndim = size(kpoints, 1)
1282 nshifts_ = optional_default(nshifts, 1)
1283 nk = product(nik_axis) * nshifts_
1284
1285 ! The MP generator is defined as k = (2*ix - N + 2*shift) * dk
1286 ! Therefore, for a single step where ix = 1,
1287 ! Delta k = 2 * dk, so to be consistent dk = 1 / 2N, such that Delta k = 1/N
1288 dk = m_one / (m_two * nik_axis)
1289
1290 safe_allocate(shell(1:nk))
1291 safe_allocate(idx(1:nk))
1292 safe_allocate_source(kpoints_unsorted(1:ndim, 1:nk), kpoints)
1293
1294 ! Squared length of the index-space coordinate
1295 do ik = 1, nk
1296 shell(ik) = sum((kpoints_unsorted(:, ik) / dk)**2)
1297 enddo
1298
1299 call robust_sort_by_abs(shell, kpoints_unsorted, idx)
1300 safe_deallocate_a(shell)
1301
1302 do ik = 1, nk
1303 kpoints(:, ik) = kpoints_unsorted(:, idx(ik))
1304 end do
1305
1306 if (present(indices)) indices = idx
1307
1308 safe_deallocate_a(idx)
1309 safe_deallocate_a(kpoints_unsorted)
1310
1312
1313 end subroutine kpoints_deterministic_sort
1314
1315
1317 subroutine kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
1318 integer, intent(in) :: dim
1319 type(lattice_vectors_t), intent(in) :: latt
1320 integer, intent(in) :: nkpoints
1321 integer, intent(in) :: nsegments
1322 integer, intent(in) :: resolution(:)
1323 real(real64), intent(in) :: highsympoints(:,:)
1324 real(real64), intent(out) :: kpoints(1:dim, 1:nkpoints)
1325 real(real64), intent(out) :: coord(1:nkpoints)
1326
1327 integer :: is, ik, kpt_ind
1328 real(real64) :: length, total_length, accumulated_length
1329 real(real64) :: kpt1(dim), kpt2(dim), vec(dim)
1330
1331 push_sub(kpoints_path_generate)
1332
1333 total_length = m_zero
1334 assert(ubound(highsympoints, dim=2) >= nsegments+1)
1335 !We first compute the total length of the k-point path
1336 do is = 1, nsegments
1337 ! We need to work in abolute coordinates to get the correct path length
1338 call kpoints_to_absolute(latt, highsympoints(:,is), kpt1)
1339 call kpoints_to_absolute(latt, highsympoints(:,is+1), kpt2)
1340
1341 vec = kpt2 - kpt1
1342 length = norm2(vec)
1343 if (resolution(is) > 0) total_length = total_length + length
1344 end do
1345
1346 accumulated_length = m_zero
1347 kpt_ind = 0
1348 !Now we generate the points
1349 do is = 1, nsegments
1350 ! We need to work in abolute coordinates to get the correct path length
1351 call kpoints_to_absolute(latt, highsympoints(:, is), kpt1)
1352 call kpoints_to_absolute(latt, highsympoints(:, is+1), kpt2)
1353
1354 vec = kpt2 - kpt1
1355 length = norm2(vec)
1356 if (length > m_epsilon) vec = vec/length
1357
1358 do ik = 1, resolution(is)
1359 kpt_ind = kpt_ind +1
1360 coord(kpt_ind) = accumulated_length + (ik-1)*length/resolution(is)
1361 kpoints(:, kpt_ind) = kpt1 + (ik-1)*length/resolution(is)*vec
1362 end do
1363 if (resolution(is) > 0) accumulated_length = accumulated_length + length
1364 end do
1365 !We add the last point
1366 kpt_ind = kpt_ind +1
1367 call kpoints_to_absolute(latt, highsympoints(:,nsegments+1), kpt1)
1368 coord(kpt_ind) = accumulated_length
1369 kpoints(:, kpt_ind) = kpt1
1370
1371 !The length of the total path is arbitrarily put to 1
1372 coord = coord/total_length
1373
1374 pop_sub(kpoints_path_generate)
1375 end subroutine kpoints_path_generate
1376
1377
1378 ! --------------------------------------------------------------------------------------------
1379 subroutine kpoints_grid_reduce(symm, time_reversal, nkpoints, dim, kpoints, weights, &
1380 map_full_to_reduced, map_full_to_symidx, symm_ops, num_symm_ops)
1381 type(symmetries_t), intent(in) :: symm
1382 logical, intent(in) :: time_reversal
1383 integer, intent(inout) :: nkpoints
1384 integer, intent(in) :: dim
1385 real(real64), intent(inout) :: kpoints(1:dim,1:nkpoints)
1386 real(real64), intent(out) :: weights(1:nkpoints)
1387 integer, intent(out) :: map_full_to_reduced(1:nkpoints)
1388 integer, intent(out) :: map_full_to_symidx(1:nkpoints)
1389 integer, intent(out) :: symm_ops(:, :)
1390 integer, intent(out) :: num_symm_ops(:)
1391
1392 integer :: nreduced
1393 real(real64), allocatable :: reduced(:, :)
1394
1395 integer ik, iop, ik2
1396 real(real64) :: tran(dim), diff(dim)
1397 real(real64), allocatable :: kweight(:)
1398
1399 real(real64) :: prec
1400
1401 push_sub(kpoints_grid_reduce)
1402
1403 ! In case of really dense k-point grid, 1/nkpoints is might be smaller
1404 ! the symprec, causing problems
1405 ! Therefore we use PREC in the following
1406 prec = min(symprec, m_one/(nkpoints*100))
1407
1408 ! reduce to irreducible zone
1409
1410 ! kmap is used to mark reducible k-points and also to
1411 ! map reducible to irreducible k-points
1413 safe_allocate(kweight(1:nkpoints))
1414 safe_allocate(reduced(1:dim, 1:nkpoints))
1415
1416 kweight = m_one / nkpoints
1417
1418 nreduced = 0
1419 map_full_to_reduced(:) = -1 ! for safety
1420 map_full_to_symidx(:) = -1 ! for safety
1421
1422 num_symm_ops = 1
1423 symm_ops(:, 1) = symmetries_identity_index(symm)
1424
1425 do ik = 1, nkpoints
1426 if (kweight(ik) < prec) cycle
1427
1428 ! new irreducible point
1429 ! has reduced non-zero weight
1430 nreduced = nreduced + 1
1431 reduced(:, nreduced) = kpoints(:, ik)
1432 map_full_to_reduced(ik) = nreduced
1433 map_full_to_symidx(ik) = 1
1434
1435 !No need to check Gamma
1436 if (maxval(abs(kpoints(:, ik))) < m_epsilon) cycle
1437
1438 if (ik == nkpoints) cycle
1439
1440 ! operate with the symmetry operations
1441 do iop = 1, symmetries_number(symm)
1442 if (iop == symmetries_identity_index(symm) .and. &
1443 .not. time_reversal) cycle ! no need to check for the identity
1444
1445 call symmetries_apply_kpoint_red(symm, iop, reduced(1:dim, nreduced), tran)
1446 !We remove potential umklapp
1447 tran = tran - anint(tran + m_half*prec)
1448
1449 ! remove (mark) k-points related to irreducible reduced by symmetry
1450 do ik2 = ik + 1, nkpoints
1451 if (kweight(ik2) < prec) cycle
1452
1453 if (.not. iop == symmetries_identity_index(symm)) then ! no need to check for the identity
1454 diff = tran - kpoints(:, ik2)
1455 diff = diff - anint(diff)
1456
1457 ! both the transformed rk ...
1458 if (sum(abs(diff)) < prec) then
1459 kweight(ik) = kweight(ik) + kweight(ik2)
1460 kweight(ik2) = m_zero
1461 map_full_to_reduced(ik2) = nreduced
1462 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1463 weights(nreduced) = kweight(ik)
1464 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1465 symm_ops(nreduced, num_symm_ops(nreduced)) = iop
1466 cycle
1467 end if
1468 end if
1469
1470 if (time_reversal) then
1471 diff = tran + kpoints(:, ik2)
1472 diff = diff - anint(diff)
1473
1474 ! and its inverse
1475 if (sum(abs(diff)) < prec) then
1476 kweight(ik) = kweight(ik) + kweight(ik2)
1477 kweight(ik2) = m_zero
1478 map_full_to_reduced(ik2) = nreduced
1479 map_full_to_symidx(ik2) = num_symm_ops(nreduced) + 1
1480 weights(nreduced) = kweight(ik)
1481 num_symm_ops(nreduced) = num_symm_ops(nreduced) + 1
1482 !We mark the symmetry+time-reversal operation as negative
1483 symm_ops(nreduced, num_symm_ops(nreduced)) = -iop
1484 end if
1485 end if
1486 end do
1487 end do
1488 end do
1489
1490 assert(sum(weights(1:nreduced)) - m_one < prec)
1491 assert(all(1 <= map_full_to_reduced(:)) .and. all(map_full_to_reduced(:) <= nreduced))
1492 assert(all(1 <= map_full_to_symidx(:)) .and. all(map_full_to_symidx(:) <= size(symm_ops, 2)))
1493
1494 nkpoints = nreduced
1495 do ik = 1, nreduced
1496 kpoints(:, ik) = reduced(:, ik)
1497 end do
1498
1499 safe_deallocate_a(kweight)
1500 safe_deallocate_a(reduced)
1501
1502 pop_sub(kpoints_grid_reduce)
1503 end subroutine kpoints_grid_reduce
1504
1505
1506 ! --------------------------------------------------------------------------------------------
1507 subroutine kpoints_fold_to_1bz(grid, latt)
1508 type(kpoints_grid_t), intent(inout) :: grid
1509 type(lattice_vectors_t), intent(in) :: latt
1510
1511 integer :: ig1, ig2, ik
1512 real(real64) :: Gvec(grid%dim, 3**grid%dim), Gvec_cart(grid%dim, 3**grid%dim)
1513 real(real64) :: vec(grid%dim), kpt(grid%dim)
1514 real(real64) :: d, dmin
1515
1516 push_sub(kpoints_fold_to_1bz)
1517
1518 !We only need to compute the first G-vectors
1519 do ig1 = 1, grid%dim
1520 do ig2 = 1, 3**grid%dim
1521 gvec(ig1, ig2) = modulo((ig2 - 1)/grid%dim**(grid%dim - ig1), 3) - 1
1522 end do
1523 end do
1524
1525 do ig1 = 1, 3**grid%dim
1526 call kpoints_to_absolute(latt, gvec(:,ig1), gvec_cart(:,ig1))
1527 end do
1528
1529 do ik = 1, grid%npoints
1530
1531 dmin = 1e10_real64
1532 do ig1 = 1, 3**grid%dim
1533 vec = gvec_cart(:,ig1) - grid%point(:,ik)
1534 d = real(sum(vec**2), real32) !Conversion to simple precision
1535 ! To avoid numerical error problems
1536 if (d < dmin) then
1537 dmin = d
1538 ig2 = ig1
1539 end if
1540 end do
1541 kpt = grid%red_point(:,ik) - gvec(:,ig2)
1542 call kpoints_to_absolute(latt, kpt, grid%point1BZ(:, ik))
1543 end do
1544
1545 pop_sub(kpoints_fold_to_1bz)
1546 end subroutine kpoints_fold_to_1bz
1547
1548
1549 ! ---------------------------------------------------------
1550 subroutine kpoints_write_info(this, iunit, namespace, absolute_coordinates)
1551 class(kpoints_t), intent(in) :: this
1552 integer, optional, intent(in) :: iunit
1553 type(namespace_t), optional, intent(in) :: namespace
1554 logical, optional, intent(in) :: absolute_coordinates
1555
1556 integer :: ik, idir
1557 character(len=100) :: str_tmp
1558 character :: index
1559
1560 push_sub(kpoints_write_info)
1561
1562 call messages_print_with_emphasis('Brillouin zone sampling', iunit, namespace)
1563
1564 if (this%method == kpoints_monkh_pack) then
1565
1566 call messages_write('Dimensions of the k-point grid =')
1567 do idir = 1, this%full%dim
1568 call messages_write(this%nik_axis(idir), fmt = '(i3,1x)')
1569 end do
1570 call messages_new_line()
1571
1572 if (.not. all(this%downsampling(1:this%full%dim) == 1)) then
1573 call messages_write('Dimensions of the q-point grid =')
1574 do idir = 1, this%full%dim
1575 call messages_write(this%niq_axis(idir), fmt = '(i3,1x)')
1576 end do
1577 call messages_new_line()
1578 end if
1579
1580 call messages_write('Total number of k-points =')
1581 call messages_write(this%full%npoints)
1582 call messages_new_line()
1583
1584 call messages_write('Number of symmetry-reduced k-points =')
1585 call messages_write(this%reduced%npoints)
1586
1587 call messages_info(iunit=iunit, namespace=namespace)
1588
1589 else
1590
1591 call messages_write('Total number of k-points =')
1592 call messages_write(this%full%npoints)
1593 call messages_new_line()
1594 call messages_info(iunit=iunit, namespace=namespace)
1595
1596 end if
1597
1598 call messages_new_line()
1599 call messages_write('List of k-points:')
1600 call messages_info(iunit=iunit, namespace=namespace)
1601
1602 write(message(1), '(6x,a)') 'ik'
1603 do idir = 1, this%full%dim
1604 index = index2axis(idir)
1605 write(str_tmp, '(9x,2a)') 'k_', index
1606 message(1) = trim(message(1)) // trim(str_tmp)
1607 end do
1608 write(str_tmp, '(6x,a)') 'Weight'
1609 message(1) = trim(message(1)) // trim(str_tmp)
1610 message(2) = '---------------------------------------------------------'
1611 call messages_info(2, iunit)
1612
1613 do ik = 1, kpoints_number(this)
1614 write(message(1),'(i8,1x)') ik
1615 do idir = 1, this%full%dim
1616 if (optional_default(absolute_coordinates, .false.)) then
1617 write(str_tmp,'(f12.4)') this%reduced%point(idir, ik)
1618 else
1619 write(str_tmp,'(f12.4)') this%reduced%red_point(idir, ik)
1620 end if
1621 message(1) = trim(message(1)) // trim(str_tmp)
1622 end do
1623 write(str_tmp,'(f12.4)') kpoints_get_weight(this, ik)
1624 message(1) = trim(message(1)) // trim(str_tmp)
1625 call messages_info(1, iunit, namespace=namespace)
1626 end do
1627
1628 call messages_info(iunit=iunit, namespace=namespace)
1629
1630 call messages_print_with_emphasis(iunit=iunit, namespace=namespace)
1631
1632 pop_sub(kpoints_write_info)
1633 end subroutine kpoints_write_info
1634
1635
1636 ! ---------------------------------------------------------
1637 logical pure function kpoints_point_is_gamma(this, ik) result(is_gamma)
1638 class(kpoints_t), intent(in) :: this
1639 integer, intent(in) :: ik
1640
1641 is_gamma = (maxval(abs(kpoints_get_point(this, ik))) < m_epsilon)
1642
1643 end function kpoints_point_is_gamma
1644
1645 !--------------------------------------------------------
1646
1647 integer pure function kpoints_get_num_symmetry_ops(this, ik) result(num)
1648 type(kpoints_t), intent(in) :: this
1649 integer, intent(in) :: ik
1650
1651 if (this%use_symmetries) then
1652 num = this%num_symmetry_ops(ik)
1653 else
1654 num = 1
1655 end if
1656
1657 end function kpoints_get_num_symmetry_ops
1658 !--------------------------------------------------------
1659
1660 integer pure function kpoints_get_symmetry_ops(this, ik, index) result(iop)
1661 type(kpoints_t), intent(in) :: this
1662 integer, intent(in) :: ik
1663 integer, intent(in) :: index
1664
1665 if (this%use_symmetries) then
1666 iop = this%symmetry_ops(ik, index)
1667 else
1668 iop = 1
1669 end if
1670
1671 end function kpoints_get_symmetry_ops
1672
1673 !--------------------------------------------------------
1683 integer pure function kpoints_get_full_symmetry_op_index(this, ifull) result(iiop)
1684 class(kpoints_t), intent(in) :: this
1685 integer, intent(in) :: ifull
1686
1687 if (this%use_symmetries) then
1688 iiop = this%map_full_to_symidx(ifull)
1689 else
1690 iiop = 1
1691 end if
1692
1694
1695 !--------------------------------------------------------
1696 logical pure function kpoints_is_valid_symmetry(this, ik, index) result(valid)
1697 type(kpoints_t), intent(in) :: this
1698 integer, intent(in) :: ik
1699 integer, intent(in) :: index
1700
1701 integer :: iop
1702
1703 valid = .false.
1704 if (this%use_symmetries) then
1705 do iop = 1, this%num_symmetry_ops(ik)
1706 if (this%symmetry_ops(ik, iop) == index) then
1707 valid = .true.
1708 return
1709 end if
1710 end do
1711 else
1712 valid = .true.
1713 end if
1714
1715 end function kpoints_is_valid_symmetry
1716
1717
1718 !--------------------------------------------------------
1719 integer function kpoints_kweight_denominator(this)
1720 type(kpoints_t), intent(in) :: this
1721
1722 integer :: denom, nik, nik_skip
1723
1725
1726 nik = this%full%npoints
1727 nik_skip = this%nik_skip
1728
1729 if (this%method == kpoints_monkh_pack) then
1730 kpoints_kweight_denominator = this%full%npoints
1731 else
1733 ! NB largest reasonable value is: # k-points x 48. from space-group symmetries
1734 do denom = 1, 100000
1735 if (all(abs(int(this%full%weight(1:nik-nik_skip)*denom + 10_real64*m_epsilon) - &
1736 this%full%weight(1:nik-nik_skip)*denom) < 100_real64*m_epsilon)) then
1738 exit
1739 end if
1740 end do
1741 end if
1744 end function kpoints_kweight_denominator
1745
1746 !--------------------------------------------------------
1747 logical pure function kpoints_have_zero_weight_path(this) result(have_zerow)
1748 class(kpoints_t), intent(in) :: this
1749
1750 if (this%nik_skip > 0) then
1751 have_zerow = .true.
1752 else
1753 have_zerow = .false.
1754 end if
1757
1758 !--------------------------------------------------------
1759 integer pure function kpoints_get_kpoint_method(this)
1760 class(kpoints_t), intent(in) :: this
1761
1762 kpoints_get_kpoint_method = this%method
1763 end function kpoints_get_kpoint_method
1764
1765 !--------------------------------------------------------
1766 real(real64) pure function kpoints_get_path_coord(this, ind) result(coord)
1767 type(kpoints_t), intent(in) :: this
1768 integer, intent(in) :: ind
1769
1770 coord = this%coord_along_path(ind)
1771 end function
1772
1773
1774
1775 !--------------------------------------------------------
1776 subroutine kpoints_check_symmetries(grid, symm, dim, time_reversal, namespace)
1777 type(kpoints_grid_t), intent(in) :: grid
1778 type(symmetries_t), intent(in) :: symm
1779 integer, intent(in) :: dim
1780 logical, intent(in) :: time_reversal
1781 type(namespace_t), intent(in) :: namespace
1782
1783 integer, allocatable :: kmap(:)
1784 real(real64) :: kpt(dim), diff(dim)
1785 integer :: nk, ik, ik2, iop
1786 type(distributed_t) :: kpt_dist
1787
1788 push_sub(kpoints_check_symmetries)
1789
1790 nk = grid%npoints
1792 !We distribute the k-points here for this routine, independently of the rest of the code
1793 call distributed_init(kpt_dist, nk, mpi_world%comm, "kpt_check")
1794
1795 !A simple map to tell if the k-point as a matching symmetric point or not
1796 safe_allocate(kmap(kpt_dist%start:kpt_dist%end))
1797
1798 do iop = 1, symmetries_number(symm)
1799 if (iop == symmetries_identity_index(symm) .and. &
1800 .not. time_reversal) cycle
1801
1802 do ik = kpt_dist%start, kpt_dist%end
1803 kmap(ik) = ik
1804 end do
1805
1806 do ik = kpt_dist%start, kpt_dist%end
1807 !We apply the symmetry
1808 call symmetries_apply_kpoint_red(symm, iop, grid%red_point(:, ik), kpt)
1809 !We remove potential umklapp
1810 kpt = kpt - anint(kpt + m_half*symprec)
1811
1812 ! remove (mark) k-points which already have a symmetric point
1813 do ik2 = 1, nk
1815 if (iop /= symmetries_identity_index(symm)) then
1816 diff = kpt - grid%red_point(:, ik2)
1817 diff = diff - anint(diff)
1818 !We found point corresponding to the symmetric kpoint
1819 if (sum(abs(diff)) < symprec) then
1820 kmap(ik) = -ik2
1821 exit
1822 end if
1823 end if
1824
1825 if (time_reversal) then
1826 diff = kpt + grid%red_point(:, ik2)
1827 diff = diff - anint(diff)
1828 !We found point corresponding to the symmetric kpoint
1829 if (sum(abs(diff)) < symprec) then
1830 kmap(ik) = -ik2
1831 exit
1832 end if
1833 end if
1834
1835 end do
1836 !In case we have not found a symnetric k-point...
1837 if (kmap(ik) == ik) then
1838 write(message(1),'(a,i5,a2,3(f7.3,a2),a)') "The reduced k-point ", ik, " (", &
1839 grid%red_point(1, ik), ", ", grid%red_point(2, ik), ", ", grid%red_point(3, ik), &
1840 ") ", "has no symmetric in the k-point grid for the following symmetry"
1841 write(message(2),'(i5,1x,a,2x,3(3i4,2x))') iop, ':', transpose(symm_op_rotation_matrix_red(symm%ops(iop)))
1842 message(3) = "Change your k-point grid or use KPointsUseSymmetries=no."
1843 call messages_fatal(3, namespace=namespace)
1844 end if
1845 end do
1846 end do
1847
1848 safe_deallocate_a(kmap)
1849
1850 call distributed_end(kpt_dist)
1851
1853 end subroutine kpoints_check_symmetries
1855 !--------------------------------------------------------
1856 logical function kpoints_is_compatible_downsampling(kpt, ik, iq) result(compatible)
1857 type(kpoints_t), intent(in) :: kpt
1858 integer, intent(in) :: ik
1859 integer, intent(in) :: iq
1860
1861 integer :: dim, idim
1862 real(real64) :: diff(kpt%reduced%dim), red(kpt%reduced%dim)
1863
1865
1866 compatible = .true.
1867 dim = kpt%reduced%dim
1868
1869 !No downsampling. We use all k-points
1870 if (all(kpt%downsampling == 1)) then
1872 return
1873 end if
1874
1875 assert(kpt%method == kpoints_monkh_pack)
1876
1877 diff = kpt%reduced%red_point(:, ik) - kpt%reduced%red_point(:, iq)
1878 do idim = 1, dim
1879 !We remove potential umklapp
1880 diff(idim) = diff(idim) - anint(diff(idim) + m_half*symprec)
1881 red(idim) = diff(idim)*kpt%nik_axis(idim)/real(kpt%downsampling(idim))
1882 if (abs(red(idim) - anint(red(idim))) > m_epsilon) then
1883 compatible = .false.
1885 return
1886 end if
1887 end do
1888
1891
1892 ! ---------------------------------------------------------
1893 integer function kpoints_nkpt_in_path(this) result(npath)
1894 class(kpoints_t), intent(in) :: this
1895
1896 npath = 0
1897 if (allocated(this%coord_along_path)) then
1898 npath = SIZE(this%coord_along_path)
1899 end if
1900
1901 end function kpoints_nkpt_in_path
1902
1903 ! ---------------------------------------------------------
1904 logical function kpoints_gamma_only(this) result(gamma_only)
1905 class(kpoints_t), intent(in) :: this
1906
1907 push_sub(kpoints_gamma_only)
1908
1909 gamma_only = kpoints_number(this) == 1 .and. kpoints_point_is_gamma(this, 1)
1910
1911 pop_sub(kpoints_gamma_only)
1912 end function kpoints_gamma_only
1913
1914 ! ---------------------------------------------------------
1915 subroutine kpoints_lattice_vectors_update(this, new_latt)
1916 class(kpoints_t), intent(inout) :: this
1917 type(lattice_vectors_t), intent(in) :: new_latt
1918
1919 integer :: ik
1920
1922
1923 this%latt = new_latt
1924
1925 do ik = 1, this%reduced%npoints
1926 call kpoints_to_absolute(this%latt, this%reduced%red_point(:, ik), this%reduced%point(:, ik))
1927 end do
1928
1929 do ik = 1, this%full%npoints
1930 call kpoints_to_absolute(this%latt, this%full%red_point(:, ik), this%full%point(:, ik))
1931 end do
1932
1934 end subroutine kpoints_lattice_vectors_update
1935
1936
1937end module kpoints_oct_m
1938
1939!! Local Variables:
1940!! mode: f90
1941!! coding: utf-8
1942!! 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:1855
subroutine, public kpoints_grid_generate(dim, naxis, nshifts, shift, kpoints, lk123)
Generates the k-points grid.
Definition: kpoints.F90:1287
subroutine, public kpoints_end(this)
Definition: kpoints.F90:1066
logical pure function kpoints_have_zero_weight_path(this)
Definition: kpoints.F90:1843
subroutine kpoints_check_symmetries(grid, symm, dim, time_reversal, namespace)
Definition: kpoints.F90:1872
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:1361
integer pure function, public kpoints_get_num_symmetry_ops(this, ik)
Definition: kpoints.F90:1743
subroutine kpoints_grid_addto(this, that)
Definition: kpoints.F90:291
real(real64) pure function, public kpoints_get_path_coord(this, ind)
Definition: kpoints.F90:1862
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:934
logical pure function, public kpoints_is_valid_symmetry(this, ik, index)
Definition: kpoints.F90:1792
integer function, public kpoints_kweight_denominator(this)
Definition: kpoints.F90:1815
subroutine, public kpoints_copy(kin, kout)
Definition: kpoints.F90:1172
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:1779
subroutine, public kpoints_path_generate(dim, latt, nkpoints, nsegments, resolution, highsympoints, kpoints, coord)
Generate the k-point along a path.
Definition: kpoints.F90:1413
integer, parameter, public kpoints_path
Definition: kpoints.F90:226
subroutine kpoints_print_info(this, namespace)
Definition: kpoints.F90:1088
pure real(real64) function, dimension(1:this%full%dim) kpoints_get_point(this, ik, absolute_coordinates)
Definition: kpoints.F90:1235
integer function, public kpoints_nkpt_in_path(this)
Definition: kpoints.F90:1989
logical function, public kpoints_is_compatible_downsampling(kpt, ik, iq)
Definition: kpoints.F90:1952
real(real64) pure function kpoints_get_weight(this, ik)
Definition: kpoints.F90:1251
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:1756
subroutine, public kpoints_read_path(this, namespace, dim)
Read the k-points path information and generate the k-points list.
Definition: kpoints.F90:787
subroutine kpoints_grid_copy(bb, aa)
Definition: kpoints.F90:273
subroutine, public kpoints_fold_to_1bz(grid, latt)
Definition: kpoints.F90:1603
integer function kpoints_get_equiv(this, ik)
Map a full-grid k-point index to its reduced-grid representative.
Definition: kpoints.F90:1269
subroutine, public kpoints_init(this, namespace, symm, dim, periodic_dim, latt)
Definition: kpoints.F90:419
subroutine, public kpoints_grid_end(this)
Definition: kpoints.F90:257
logical pure function, public kpoints_point_is_gamma(this, ik)
Definition: kpoints.F90:1733
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.
Definition: kpoints.F90:498
integer, parameter, public kpoints_user
Definition: kpoints.F90:226
logical function kpoints_gamma_only(this)
Definition: kpoints.F90:2000
subroutine, public kpoints_lattice_vectors_update(this, new_latt)
Definition: kpoints.F90:2011
subroutine, public kpoints_to_reduced(latt, kin, kout)
Definition: kpoints.F90:1158
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:1226
subroutine, public kpoints_to_absolute(latt, kin, kout)
Definition: kpoints.F90:1145
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:1476
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:1646
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
int true(void)