root/trunk/src/ions/kpoints.F90 @ 6350

Revision 6350, 11.7 KB (checked in by fulvio, 6 months ago)

I modified the k-points grid generation scheme: now the (full) k-p. grid is
the same generated by Abinit.

Line 
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., 59 Temple Place - Suite 330, Boston, MA
16!! 02111-1307, USA.
17!!
18!! $Id: kpoints.F90 5635 2009-06-25 14:55:35Z nitsche $
19
20#include "global.h"
21 
22module kpoints_m
23  use datasets_m
24  use geometry_m
25  use global_m
26  use loct_m
27  use parser_m
28  use messages_m
29  use profiling_m
30  use unit_m
31  use unit_system_m
32 
33  implicit none
34 
35  private
36  public ::       &
37    kpoints_t,    &
38    kpoints_init, &
39    kpoints_end,  &
40    kpoints_copy
41
42
43  type kpoints_t
44    integer        :: method
45
46    integer        :: nik_full             ! number of k-points in full Brillouin zone
47    FLOAT, pointer :: points_full(:,:)     ! k-points in absolute coordinates
48    FLOAT, pointer :: points_full_red(:,:) ! k-points in reduced coordinates
49    FLOAT, pointer :: weights_full(:)      ! weights for the k-point integrations
50
51    integer        :: nik                  ! number of k-points in the irreducible zone
52    logical        :: use_symmetries
53    logical        :: use_inversion
54
55    ! For the modified Monkhorst-Pack  scheme
56    integer        :: nik_axis(MAX_DIM)    ! number of MP divisions
57    FLOAT          :: shifts(MAX_DIM)      !
58
59  end type kpoints_t
60
61  integer, parameter ::        &
62    KPOINTS_GAMMA       =  1,  &
63    KPOINTS_MONKH_PACK  =  2,  &
64    KPOINTS_USER        =  3
65
66contains
67
68
69  ! ---------------------------------------------------------
70  subroutine kpoints_init(this, dim, periodic_dim, rlattice, klattice, geo)
71    type(kpoints_t),    intent(out) :: this
72    integer,            intent(in)  :: dim, periodic_dim
73    FLOAT,              intent(in)  :: rlattice(:,:), klattice(:,:)
74    type(geometry_t),   intent(in)  :: geo
75
76    call push_sub('kpoints.kpoints_init')
77
78    if(periodic_dim==0) then
79      this%method = KPOINTS_GAMMA
80      call read_MP(.true.)
81      call generate_MP()
82    else
83      if(read_user_kpoints()) then
84        this%method = KPOINTS_USER
85      else
86        this%method = KPOINTS_MONKH_PACK
87        call read_MP(.false.)
88        call generate_MP()
89      end if
90    end if
91
92    call pop_sub()
93
94  contains
95    ! ---------------------------------------------------------
96    subroutine read_MP(gamma_only)
97      logical, intent(in) :: gamma_only
98
99      logical       :: gamma_only_
100      integer       :: ii
101      type(block_t) :: blk
102
103      call push_sub('kpoints.kpoints_init.read_MP')
104
105      call messages_obsolete_variable('KPointsMonkhorstPack', 'KPointsGrid')
106
107      !%Variable KPointsGrid
108      !%Type block
109      !%Default Gamma-point only
110      !%Section Mesh::KPoints
111      !%Description
112      !% When this block is given (and the <tt>KPoints</tt> block is not present),
113      !% <i>k</i>-points are distributed in a uniform grid.
114      !%
115      !% The first row of the block is a triplet of integers defining
116      !% the number of <i>k</i>-points to be used along each direction
117      !% in reciprocal space. The numbers refer to the whole Brillouin
118      !% zone, and the actual number of <i>k</i>-points is usually
119      !% reduced exploiting the symmetries of the system.  By default
120      !% the grid will always include the Gamma point. An optional
121      !% second row can specify a shift in the <i>k</i>-points.
122      !%
123      !% For example, the following input samples the BZ with 100 points in the
124      !% <i>xy</i>-plane of reciprocal space:
125      !%
126      !% <tt>%KPointsGrid
127      !% <br>&nbsp;&nbsp;10 | 10 | 1
128      !% <br>%</tt>
129      !%
130      !%End
131
132      gamma_only_ = gamma_only
133      if(.not.gamma_only_) gamma_only_ = (parse_block(datasets_check('KPointsGrid'), blk) .ne. 0)
134
135      this%nik_axis(:) = 1
136      this%shifts(:)   = M_ZERO
137
138      if(.not.gamma_only_) then
139        do ii = 1, periodic_dim
140          call parse_block_integer(blk, 0, ii-1, this%nik_axis(ii))
141        end do
142
143        if (any(this%nik_axis < 1)) then
144          message(1) = 'Input: KPointsGrid is not valid'
145          call write_fatal(1)
146        end if
147
148        if(parse_block_n(blk) > 1) then ! we have a shift
149          do ii = 1, periodic_dim
150            call parse_block_float(blk, 1, ii-1, this%shifts(ii))
151          end do
152        end if
153
154        call parse_block_end(blk)
155      end if
156
157      this%nik_full = product(this%nik_axis(:))
158
159      SAFE_ALLOCATE(this%points_full    (1:MAX_DIM, 1:this%nik_full))
160      SAFE_ALLOCATE(this%points_full_red(1:MAX_DIM, 1:this%nik_full))
161      SAFE_ALLOCATE(this%weights_full(1:this%nik_full))
162
163      this%points_full(:,:)     = M_ZERO
164      this%points_full_red(:,:) = M_ZERO
165      this%weights_full(:)      = M_ONE / TOFLOAT(this%nik_full)
166
167      call pop_sub()
168    end subroutine read_MP
169
170
171    ! ---------------------------------------------------------
172    subroutine generate_MP()
173      !generate k-points using the MP scheme
174      FLOAT :: dx(1:MAX_DIM)
175      integer :: ii, jj, kk, ix(1:MAX_DIM), idir, ikp, odd_shifts(1:MAX_DIM)
176
177      call push_sub('kpoints.kpoints_init.generate_MP')
178
179      dx(:) = M_ONE/TOFLOAT(2*this%nik_axis(:))
180      odd_shifts(:) = M_ZERO
181      do idir = 1, periodic_dim
182        if(mod(this%nik_axis(idir), 2) == 1) odd_shifts(idir) = 1
183      end do
184
185      ikp = 0
186      ix(:) = M_ZERO
187      do ii = 1, this%nik_axis(1)
188         do jj = 1, this%nik_axis(2)
189            do kk = 1, this%nik_axis(3)
190               ikp = ikp + 1
191               ix(1:3) = (/ii, jj, kk/)
192
193               do idir = 1, periodic_dim
194                  this%points_full_red(idir, ikp) = TOFLOAT(2*ix(idir) - this%nik_axis(idir) - odd_shifts(idir))
195                  this%points_full_red(idir, ikp) = (this%points_full_red(idir, ikp) + M_TWO*this%shifts(idir))*dx(idir)
196                  this%points_full_red(idir, ikp) = mod(this%points_full_red(idir, ikp) + M_HALF, M_ONE) - M_HALF
197                   
198               end do
199               print *,this%points_full_red(: ,ikp)   
200            end do
201         end do
202      end do
203
204      call pop_sub()
205
206    end subroutine generate_MP
207
208
209    ! ---------------------------------------------------------
210    logical function read_user_kpoints()
211      type(block_t) :: blk
212      logical :: reduced
213      integer :: ik, idim
214
215      call push_sub('kpoints.kpoints_init.read_user_kpoints')
216
217      !%Variable KPoints
218      !%Type block
219      !%Section Mesh::KPoints
220      !%Description
221      !% This block defines an explicit set of <i>k</i>-points and their weights for
222      !% a periodic-system calculation. The first column is the weight
223      !% of each <i>k</i>-point and the following are the components of the <i>k</i>-point
224      !% vector. You only need to specify the components for the
225      !% periodic directions. Note that the <i>k</i>-points should be given in
226      !% Cartesian coordinates (not in reduced coordinates), <i>i.e.</i>
227      !% what Octopus writes in a line in the ground-state standard output as
228      !% <tt>#k =   1, k = (    0.154000,    0.154000,    0.154000)</tt>.
229      !%
230      !% For example, if you want to include only the Gamma point, you can
231      !% use:
232      !%
233      !% <tt>%KPoints
234      !% <br>&nbsp;&nbsp;1.0 | 0 | 0 | 0
235      !% <br>%</tt>
236      !%
237      !%End
238
239      !%Variable KPointsReduced
240      !%Type block
241      !%Section Mesh::KPoints
242      !%Description
243      !% Same as the block <tt>KPoints</tt> but this time the input is given in reduced
244      !% coordinates.
245      !%End
246
247      this%nik_full = 0
248      reduced = .false.
249      if(parse_block(datasets_check('KPoints'), blk).ne.0) then
250        if(parse_block(datasets_check('KPointsReduced'), blk) == 0) then
251          reduced = .true.
252        else
253          read_user_kpoints = .false.
254          call pop_sub(); return
255        end if
256      end if
257      read_user_kpoints = .true.
258
259      this%nik_full = parse_block_n(blk)
260
261      SAFE_ALLOCATE(this%points_full(1:MAX_DIM, 1:this%nik_full))
262      SAFE_ALLOCATE(this%points_full_red(1:MAX_DIM, 1:this%nik_full))
263      SAFE_ALLOCATE(this%weights_full(1:this%nik_full))
264
265      this%points_full  = M_ZERO
266      this%weights_full = M_ZERO
267
268      if(reduced) then
269        do ik = 1, this%nik_full
270          call parse_block_float(blk, ik - 1, 0, this%weights_full(ik))
271          do idim = 1, periodic_dim
272            call parse_block_float(blk, ik - 1, idim, this%points_full_red(idim, ik))
273          end do
274        end do
275
276        ! generate also the absolute coordinates
277        do ik = 1, this%nik_full
278          call kpoints_to_absolute(klattice, this%points_full_red(:,ik), this%points_full(:,ik))
279        end do
280      else
281        do ik = 1, this%nik_full
282          call parse_block_float(blk, ik - 1, 0, this%weights_full(ik))
283          do idim = 1, periodic_dim
284            call parse_block_float(blk, ik - 1, idim, this%points_full(idim, ik))
285          end do
286        end do
287
288        do ik = 1, this%nik_full
289          ! k-points have 1/length units
290          this%points_full(:, ik) = units_to_atomic(unit_one/units_inp%length, this%points_full(:, ik))
291
292          ! generate also the reduced coordinates
293          call kpoints_to_reduced(rlattice, this%points_full(:,ik), this%points_full_red(:,ik))
294        end do
295      end if
296      call parse_block_end(blk)
297
298      write(message(1), '(a,i4,a)') 'Input: ', this%nik_full, ' k-points were read from the input file'
299      call write_info(1)
300
301      call pop_sub()
302    end function read_user_kpoints
303
304  end subroutine kpoints_init
305
306
307  ! ---------------------------------------------------------
308  subroutine kpoints_end(this)
309    type(kpoints_t), intent(inout) :: this
310
311    SAFE_DEALLOCATE_P(this%points_full)
312    SAFE_DEALLOCATE_P(this%points_full_red)
313    SAFE_DEALLOCATE_P(this%weights_full)
314
315  end subroutine kpoints_end
316
317
318  ! ---------------------------------------------------------
319  subroutine kpoints_to_absolute(klattice, kin, kout)
320    FLOAT, intent(in)  :: klattice(:,:), kin(:)
321    FLOAT, intent(out) :: kout(:)
322
323    integer :: ii
324
325    call push_sub('kpoints.kpoints_to_absolute')
326
327    kout(:) = M_ZERO
328    do ii = 1, MAX_DIM
329      kout(:) = kout(:) + kin(ii)*klattice(:, ii)
330    end do
331
332    call pop_sub()
333
334  end subroutine kpoints_to_absolute
335
336
337  ! ---------------------------------------------------------
338  subroutine kpoints_to_reduced(rlattice, kin, kout)
339    FLOAT, intent(in)  :: rlattice(:,:)
340    FLOAT, intent(in)  :: kin(:)
341    FLOAT, intent(out) :: kout(:)
342
343    integer :: ii
344
345    call push_sub('kpoints.kpoints_to_reduced')
346
347    kout(:) = M_ZERO
348    do ii = 1, MAX_DIM
349      kout(:) = kout(:) + kin(ii)*rlattice(ii, :)
350    end do
351    kout(:) = kout(:) / (M_TWO*M_PI)
352
353    call pop_sub()
354  end subroutine kpoints_to_reduced
355
356
357  ! ---------------------------------------------------------
358  subroutine kpoints_copy(kout, kin)
359    type(kpoints_t), intent(out) :: kout
360    type(kpoints_t), intent(in)  :: kin
361
362    call push_sub('kpoints.kpoints_copy')
363
364    kout%method = kin%method
365    kout%nik_full = kin%nik_full
366    call loct_pointer_copy(kout%points_full, kin%points_full)
367    call loct_pointer_copy(kout%points_full_red, kin%points_full_red)
368    call loct_pointer_copy(kout%weights_full, kin%weights_full)
369
370    kout%nik = kin%nik
371    kout%use_symmetries = kin%use_symmetries
372    kout%use_inversion  = kin%use_inversion
373
374    kout%nik_axis = kin%nik_axis
375    kout%shifts = kin%shifts
376
377    call pop_sub()
378  end subroutine kpoints_copy
379
380end module kpoints_m
381
382!! Local Variables:
383!! mode: f90
384!! coding: utf-8
385!! End:
Note: See TracBrowser for help on using the browser.