1import io
2import re
3
4import numpy as np
5import pytest
6
7from ase.build import bulk
8from ase.io import write
9from ase.io.elk import parse_elk_eigval, read_elk
10from ase.units import Hartree, Bohr
11
12
13def test_elk_in():
14    atoms = bulk('Si')
15    buf = io.StringIO()
16    write(buf, atoms, format='elk-in', parameters={'mockparameter': 17})
17    text = buf.getvalue()
18    print(text)
19    assert 'avec' in text
20    assert re.search(r'mockparameter\s+17\n', text, re.M)
21
22
23mock_elk_eigval_out = """
242 : nkpt
253 : nstsv
26
271   0.0 0.0 0.0 : k-point, vkl
28(state, eigenvalue and occupancy below)
291 -1.0 2.0
302 -0.5 1.5
313  1.0 0.0
32
33
342   0.0 0.1 0.2 : k-point, vkl
35(state, <blah blah>)
361 1.0 1.9
372 1.1 1.8
383 1.2 1.7
39"""
40
41
42def test_parse_eigval():
43    fd = io.StringIO(mock_elk_eigval_out)
44    dct = dict(parse_elk_eigval(fd))
45    eig = dct['eigenvalues'] / Hartree
46    occ = dct['occupations']
47    kpts = dct['ibz_kpoints']
48    assert len(eig) == 1
49    assert len(occ) == 1
50    assert pytest.approx(eig[0]) == [[-1.0, -0.5, 1.0], [1.0, 1.1, 1.2]]
51    assert pytest.approx(occ[0]) == [[2.0, 1.5, 0.0], [1.9, 1.8, 1.7]]
52    assert pytest.approx(kpts) == [[0., 0., 0.], [0.0, 0.1, 0.2]]
53
54
55elk_geometry_out = """
56scale
57 1.0
58
59scale1
60 1.0
61
62scale2
63 1.0
64
65scale3
66 1.0
67
68avec
69   1.0 0.1 0.2
70   0.3 2.0 0.4
71   0.5 0.6 3.0
72
73atoms
74   1                                    : nspecies
75'Si.in'                                 : spfname
76   2                                    : natoms; atpos, bfcmt below
77    0.1 0.2 0.3    0.0 0.0 0.0
78    0.4 0.5 0.6    0.0 0.0 0.0
79"""
80
81
82def test_read_elk():
83    atoms = read_elk(io.StringIO(elk_geometry_out))
84    assert str(atoms.symbols) == 'Si2'
85    assert all(atoms.pbc)
86    assert atoms.cell / Bohr == pytest.approx(np.array([
87        [1.0, 0.1, 0.2],
88        [0.3, 2.0, 0.4],
89        [0.5, 0.6, 3.0],
90    ]))
91    assert atoms.get_scaled_positions() == pytest.approx(np.array([
92        [0.1, 0.2, 0.3],
93        [0.4, 0.5, 0.6],
94    ]))
95