Statistiques
| Révision :

root / ase / dft / kpoints.py @ 20

Historique | Voir | Annoter | Télécharger (9,57 ko)

1
from __future__ import division
2
import numpy as np
3

    
4

    
5
def monkhorst_pack(size):
6
    """Construct a uniform sampling of k-space of given size."""
7
    if np.less_equal(size, 0).any():
8
        raise ValueError('Illegal size: %s' % list(size))
9
    kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3))
10
    return (kpts + 0.5) / size - 0.5
11

    
12

    
13
def get_monkhorst_shape(kpts, tol=1e-5):
14
    """Return the number of k-points along each axis of input Monkhorst pack.
15

16
    The set of k-points must not have been symmetry reduced.
17
    """
18
    nkpts = len(kpts)
19
    if nkpts == 1:
20
        return np.ones(3, int)
21
    
22
    Nk_c = np.zeros(3, int)
23
    for c in range(3):
24
        # Determine increment between kpoints along current axis
25
        DeltaK = max(np.diff(np.sort(kpts[:, c])))
26

    
27
        # Determine number of kpoints as inverse of distance between kpoints
28
        if DeltaK > tol:
29
            Nk_c[c] = int(round(1. / DeltaK))
30
        else:
31
            Nk_c[c] = 1
32
    return Nk_c
33

    
34

    
35
def kpoint_convert(cell_cv, skpts_kc=None, ckpts_kv=None):
36
    """Convert k-points between scaled and cartesian coordinates.
37

38
    Given the atomic unit cell, and either the scaled or cartesian k-point
39
    coordinates, the other is determined.
40

41
    The k-point arrays can be either a single point, or a list of points,
42
    i.e. the dimension k can be empty or multidimensional.
43
    """
44
    if ckpts_kv is None:
45
        icell_cv = 2 * np.pi * np.linalg.inv(cell_cv).T
46
        return np.dot(skpts_kc, icell_cv)
47
    elif skpts_kc is None:
48
        return np.dot(ckpts_kv, cell_cv.T) / (2 * np.pi)
49
    else:
50
        raise KeyError('Either scaled or cartesian coordinates must be given.')
51

    
52

    
53
def get_bandpath(points, cell, npoints=50):
54
    """Make a list of kpoints defining the path between the given points.
55

56
    points: list
57
        List of special IBZ point pairs, e.g. ``points =
58
        [W, L, Gamma, X, W, K]``.  These should be given in
59
        scaled coordinates.
60
    cell: 3x3 ndarray
61
        Unit cell of the atoms.
62
    npoints: int
63
        Length of the output kpts list.
64

65
    Return list of k-points, list of x-coordinates and list of
66
    x-coordinates of special points."""
67

    
68
    points = np.asarray(points)
69
    dists = points[1:] - points[:-1]
70
    lengths = [np.linalg.norm(d) for d in kpoint_convert(cell, skpts_kc=dists)]
71
    length = sum(lengths)
72
    kpts = []
73
    x0 = 0
74
    x = []
75
    X = [0]
76
    for P, d, L in zip(points[:-1], dists, lengths):
77
        n = int(round(L * (npoints - 1 - len(x)) / (length - x0)))
78
        for t in np.linspace(0, 1, n, endpoint=False):
79
            kpts.append(P + t * d)
80
            x.append(x0 + t * L)
81
        x0 += L
82
        X.append(x0)
83
    kpts.append(points[-1])
84
    x.append(x0)
85
    return kpts, np.array(x), np.array(X)
86

    
87

    
88
# The following is a list of the critical points in the 1. Brillouin zone
89
# for some typical crystal structures.
90
# (In units of the reciprocal basis vectors)
91
# See http://en.wikipedia.org/wiki/Brillouin_zone
92
ibz_points = {'cubic': {'Gamma': [0,     0,     0    ],
93
                        'X':     [0,     0 / 2, 1 / 2],
94
                        'R':     [1 / 2, 1 / 2, 1 / 2],
95
                        'M':     [0 / 2, 1 / 2, 1 / 2]},
96

    
97
              'fcc':   {'Gamma': [0,     0,     0    ],
98
                        'X':     [1 / 2, 0,     1 / 2],
99
                        'W':     [1 / 2, 1 / 4, 3 / 4],
100
                        'K':     [3 / 8, 3 / 8, 3 / 4],
101
                        'U':     [5 / 8, 1 / 4, 5 / 8],
102
                        'L':     [1 / 2, 1 / 2, 1 / 2]},
103

    
104
              'bcc':   {'Gamma': [0,      0,     0    ],
105
                        'H':     [1 / 2, -1 / 2, 1 / 2],
106
                        'N':     [0,      0,     1 / 2],
107
                        'P':     [1 / 4,  1 / 4, 1 / 4]},
108

    
109
              }
110

    
111
# ChadiCohen k point grids. The k point grids are given in units of the
112
# reciprocal unit cell. The variables are named after the following
113
# convention: cc+'<Nkpoints>'+_+'shape'. For example an 18 k point
114
# sq(3)xsq(3) is named 'cc18_sq3xsq3'.
115

    
116
cc6_1x1 = np.array([1, 1, 0, 1, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
117
    0, 1, 0] ).reshape((6, 3)) / 3.0
118

    
119
cc12_2x3 = np.array([3, 4, 0, 3, 10, 0, 6, 8, 0, 3, -2, 0, 6, -4, 0,
120
    6, 2, 0, -3, 8, 0, -3, 2, 0, -3, -4, 0, -6, 4, 0, -6, -2, 0, -6,
121
    -8, 0] ).reshape((12, 3)) / 18.0
122

    
123
cc18_sq3xsq3 = np.array([2, 2, 0, 4, 4, 0, 8, 2, 0, 4, -2, 0, 8, -4,
124
    0, 10, -2, 0, 10, -8, 0, 8, -10, 0, 2, -10, 0, 4, -8, 0, -2, -8,
125
    0, 2, -4, 0, -4, -4, 0, -2, -2, 0, -4, 2, 0, -2, 4, 0, -8, 4, 0,
126
    -4, 8, 0] ).reshape((18, 3)) / 18.0
127

    
128
cc18_1x1 = np.array([2, 4, 0, 2, 10, 0, 4, 8, 0, 8, 4, 0, 8, 10, 0,
129
    10, 8, 0, 2, -2, 0, 4, -4, 0, 4, 2, 0, -2, 8, 0, -2, 2, 0, -2, -4,
130
    0, -4, 4, 0, -4, -2, 0, -4, -8, 0, -8, 2, 0, -8, -4, 0, -10, -2,
131
    0] ).reshape((18, 3)) / 18.0
132

    
133
cc54_sq3xsq3 = np.array([4, -10, 0, 6, -10, 0, 0, -8, 0, 2, -8, 0, 6,
134
    -8, 0, 8, -8, 0, -4, -6, 0, -2, -6, 0, 2, -6, 0, 4, -6, 0, 8, -6,
135
    0, 10, -6, 0, -6, -4, 0, -2, -4, 0, 0, -4, 0, 4, -4, 0, 6, -4, 0,
136
    10, -4, 0, -6, -2, 0, -4, -2, 0, 0, -2, 0, 2, -2, 0, 6, -2, 0, 8,
137
    -2, 0, -8, 0, 0, -4, 0, 0, -2, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, 0,
138
    -8, 2, 0, -6, 2, 0, -2, 2, 0, 0, 2, 0, 4, 2, 0, 6, 2, 0, -10, 4,
139
    0, -6, 4, 0, -4, 4, 0, 0, 4, 0, 2, 4, 0, 6, 4, 0, -10, 6, 0, -8,
140
    6, 0, -4, 6, 0, -2, 6, 0, 2, 6, 0, 4, 6, 0, -8, 8, 0, -6, 8, 0,
141
    -2, 8, 0, 0, 8, 0, -6, 10, 0, -4, 10, 0]).reshape((54, 3)) / 18.0
142

    
143
cc54_1x1 = np.array([2, 2, 0, 4, 4, 0, 8, 8, 0, 6, 8, 0, 4, 6, 0, 6,
144
    10, 0, 4, 10, 0, 2, 6, 0, 2, 8, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, -2,
145
    6, 0, -2, 4, 0, -4, 6, 0, -6, 4, 0, -4, 2, 0, -6, 2, 0, -2, 0, 0,
146
    -4, 0, 0, -8, 0, 0, -8, -2, 0, -6, -2, 0, -10, -4, 0, -10, -6, 0,
147
    -6, -4, 0, -8, -6, 0, -2, -2, 0, -4, -4, 0, -8, -8, 0, 4, -2, 0,
148
    6, -2, 0, 6, -4, 0, 2, 0, 0, 4, 0, 0, 6, 2, 0, 6, 4, 0, 8, 6, 0,
149
    8, 0, 0, 8, 2, 0, 10, 4, 0, 10, 6, 0, 2, -4, 0, 2, -6, 0, 4, -6,
150
    0, 0, -2, 0, 0, -4, 0, -2, -6, 0, -4, -6, 0, -6, -8, 0, 0, -8, 0,
151
    -2, -8, 0, -4, -10, 0, -6, -10, 0] ).reshape((54, 3)) / 18.0
152

    
153
cc162_sq3xsq3 = np.array([-8, 16, 0, -10, 14, 0, -7, 14, 0, -4, 14,
154
    0, -11, 13, 0, -8, 13, 0, -5, 13, 0, -2, 13, 0, -13, 11, 0, -10,
155
    11, 0, -7, 11, 0, -4, 11, 0, -1, 11, 0, 2, 11, 0, -14, 10, 0, -11,
156
    10, 0, -8, 10, 0, -5, 10, 0, -2, 10, 0, 1, 10, 0, 4, 10, 0, -16,
157
    8, 0, -13, 8, 0, -10, 8, 0, -7, 8, 0, -4, 8, 0, -1, 8, 0, 2, 8, 0,
158
    5, 8, 0, 8, 8, 0, -14, 7, 0, -11, 7, 0, -8, 7, 0, -5, 7, 0, -2, 7,
159
    0, 1, 7, 0, 4, 7, 0, 7, 7, 0, 10, 7, 0, -13, 5, 0, -10, 5, 0, -7,
160
    5, 0, -4, 5, 0, -1, 5, 0, 2, 5, 0, 5, 5, 0, 8, 5, 0, 11, 5, 0,
161
    -14, 4, 0, -11, 4, 0, -8, 4, 0, -5, 4, 0, -2, 4, 0, 1, 4, 0, 4, 4,
162
    0, 7, 4, 0, 10, 4, 0, -13, 2, 0, -10, 2, 0, -7, 2, 0, -4, 2, 0,
163
    -1, 2, 0, 2, 2, 0, 5, 2, 0, 8, 2, 0, 11, 2, 0, -11, 1, 0, -8, 1,
164
    0, -5, 1, 0, -2, 1, 0, 1, 1, 0, 4, 1, 0, 7, 1, 0, 10, 1, 0, 13, 1,
165
    0, -10, -1, 0, -7, -1, 0, -4, -1, 0, -1, -1, 0, 2, -1, 0, 5, -1,
166
    0, 8, -1, 0, 11, -1, 0, 14, -1, 0, -11, -2, 0, -8, -2, 0, -5, -2,
167
    0, -2, -2, 0, 1, -2, 0, 4, -2, 0, 7, -2, 0, 10, -2, 0, 13, -2, 0,
168
    -10, -4, 0, -7, -4, 0, -4, -4, 0, -1, -4, 0, 2, -4, 0, 5, -4, 0,
169
    8, -4, 0, 11, -4, 0, 14, -4, 0, -8, -5, 0, -5, -5, 0, -2, -5, 0,
170
    1, -5, 0, 4, -5, 0, 7, -5, 0, 10, -5, 0, 13, -5, 0, 16, -5, 0, -7,
171
    -7, 0, -4, -7, 0, -1, -7, 0, 2, -7, 0, 5, -7, 0, 8, -7, 0, 11, -7,
172
    0, 14, -7, 0, 17, -7, 0, -8, -8, 0, -5, -8, 0, -2, -8, 0, 1, -8,
173
    0, 4, -8, 0, 7, -8, 0, 10, -8, 0, 13, -8, 0, 16, -8, 0, -7, -10,
174
    0, -4, -10, 0, -1, -10, 0, 2, -10, 0, 5, -10, 0, 8, -10, 0, 11,
175
    -10, 0, 14, -10, 0, 17, -10, 0, -5, -11, 0, -2, -11, 0, 1, -11, 0,
176
    4, -11, 0, 7, -11, 0, 10, -11, 0, 13, -11, 0, 16, -11, 0, -1, -13,
177
    0, 2, -13, 0, 5, -13, 0, 8, -13, 0, 11, -13, 0, 14, -13, 0, 1,
178
    -14, 0, 4, -14, 0, 7, -14, 0, 10, -14, 0, 13, -14, 0, 5, -16, 0,
179
    8, -16, 0, 11, -16, 0, 7, -17, 0, 10, -17, 0]).reshape((162, 3)) / 27.0
180

    
181
cc162_1x1 = np.array([-8, -16, 0, -10, -14, 0, -7, -14, 0, -4, -14,
182
    0, -11, -13, 0, -8, -13, 0, -5, -13, 0, -2, -13, 0, -13, -11, 0,
183
    -10, -11, 0, -7, -11, 0, -4, -11, 0, -1, -11, 0, 2, -11, 0, -14,
184
    -10, 0, -11, -10, 0, -8, -10, 0, -5, -10, 0, -2, -10, 0, 1, -10,
185
    0, 4, -10, 0, -16, -8, 0, -13, -8, 0, -10, -8, 0, -7, -8, 0, -4,
186
    -8, 0, -1, -8, 0, 2, -8, 0, 5, -8, 0, 8, -8, 0, -14, -7, 0, -11,
187
    -7, 0, -8, -7, 0, -5, -7, 0, -2, -7, 0, 1, -7, 0, 4, -7, 0, 7, -7,
188
    0, 10, -7, 0, -13, -5, 0, -10, -5, 0, -7, -5, 0, -4, -5, 0, -1,
189
    -5, 0, 2, -5, 0, 5, -5, 0, 8, -5, 0, 11, -5, 0, -14, -4, 0, -11,
190
    -4, 0, -8, -4, 0, -5, -4, 0, -2, -4, 0, 1, -4, 0, 4, -4, 0, 7, -4,
191
    0, 10, -4, 0, -13, -2, 0, -10, -2, 0, -7, -2, 0, -4, -2, 0, -1,
192
    -2, 0, 2, -2, 0, 5, -2, 0, 8, -2, 0, 11, -2, 0, -11, -1, 0, -8,
193
    -1, 0, -5, -1, 0, -2, -1, 0, 1, -1, 0, 4, -1, 0, 7, -1, 0, 10, -1,
194
    0, 13, -1, 0, -10, 1, 0, -7, 1, 0, -4, 1, 0, -1, 1, 0, 2, 1, 0, 5,
195
    1, 0, 8, 1, 0, 11, 1, 0, 14, 1, 0, -11, 2, 0, -8, 2, 0, -5, 2, 0,
196
    -2, 2, 0, 1, 2, 0, 4, 2, 0, 7, 2, 0, 10, 2, 0, 13, 2, 0, -10, 4,
197
    0, -7, 4, 0, -4, 4, 0, -1, 4, 0, 2, 4, 0, 5, 4, 0, 8, 4, 0, 11, 4,
198
    0, 14, 4, 0, -8, 5, 0, -5, 5, 0, -2, 5, 0, 1, 5, 0, 4, 5, 0, 7, 5,
199
    0, 10, 5, 0, 13, 5, 0, 16, 5, 0, -7, 7, 0, -4, 7, 0, -1, 7, 0, 2,
200
    7, 0, 5, 7, 0, 8, 7, 0, 11, 7, 0, 14, 7, 0, 17, 7, 0, -8, 8, 0,
201
    -5, 8, 0, -2, 8, 0, 1, 8, 0, 4, 8, 0, 7, 8, 0, 10, 8, 0, 13, 8, 0,
202
    16, 8, 0, -7, 10, 0, -4, 10, 0, -1, 10, 0, 2, 10, 0, 5, 10, 0, 8,
203
    10, 0, 11, 10, 0, 14, 10, 0, 17, 10, 0, -5, 11, 0, -2, 11, 0, 1,
204
    11, 0, 4, 11, 0, 7, 11, 0, 10, 11, 0, 13, 11, 0, 16, 11, 0, -1,
205
    13, 0, 2, 13, 0, 5, 13, 0, 8, 13, 0, 11, 13, 0, 14, 13, 0, 1, 14,
206
    0, 4, 14, 0, 7, 14, 0, 10, 14, 0, 13, 14, 0, 5, 16, 0, 8, 16, 0,
207
    11, 16, 0, 7, 17, 0, 10, 17, 0]).reshape((162, 3)) / 27.0